Advertisement
djazz

JJ2 Bot for Node.js

Mar 10th, 2012
329
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. 'use strict';
  2.  
  3. // created by djazz
  4.  
  5. var BOT_NAME = '[bot]';
  6.  
  7. var info = {
  8.     ip: '127.0.0.1',
  9.     port: 10052
  10. }
  11.  
  12. var net = require('net');
  13. var dgram = require('dgram');
  14.  
  15. // Zero fill
  16. function zfs(v, width) {
  17.     v = v+'';
  18.     if (typeof width !== 'number') width = v.length+1;
  19.     return new Array(width-v.length+1).join("0")+v;
  20. }
  21.  
  22. function Server (config) {
  23.     if(!config) config = {};
  24.     this.ip = config.ip;
  25.     this.port = parseInt(config.port, 10) || 0;
  26.     this.address = this.ip+":"+this.port;
  27.     this['private'] = !!(config['private'] || false);
  28.     this.gametype = parseInt(config.gametype, 10) || 0;
  29.     this.version = new Buffer(4);
  30.     if(Buffer.isBuffer(config.version)) {
  31.         config.version.copy(this.version, 0, 0, 4);
  32.     }
  33.     else if(typeof config.version === 'string') {
  34.         this.version.write(config.version, 0, 4, 'binary');
  35.     }
  36.     if(!config.capacity) config.capacity = [0, 0];
  37.     this.capacity = [+config.capacity[0] || 0, +config.capacity[1] || 0];
  38.     this.servername = config.servername || '';
  39. };
  40. Server.prototype.toJSON = function () {
  41.     return {
  42.         ip: this.ip,
  43.         port: this.port,
  44.         address: this.address,
  45.         'private': this['private'],
  46.         gametype: this.gametype,
  47.         version: this.version.toString('binary'),
  48.         capacity: this.capacity,
  49.         servername: this.servername
  50.     };
  51. };
  52.  
  53. function udpchecksum (buf) {
  54.     var x = 1, y = 1, size = buf.length;
  55.     for(var i = 2; i < size; i+=1) {
  56.         x += buf[i];
  57.         y += x;
  58.     }
  59.     buf[0] = x % 251;
  60.     buf[1] = y % 251;
  61.     return buf;
  62. };
  63.  
  64. var disconnectMessages = {
  65.     1: "Server is full",
  66.     2: "Version different",
  67.     3: "Server is full",
  68.     4: "Error during handshaking",
  69.     5: "Feature not supported in shareware",
  70.     6: "Error downloading level",
  71.     7: "Connection lost",
  72.     8: "Winsock error",
  73.     9: "Connection timed out",
  74.     10:"Server stopped",
  75.     11:"Kicked off",
  76.     12:"Banned",
  77.  
  78.     17:"Unauthorized file request",
  79.     18:"No splitscreeners allowed"
  80. };
  81. var actionSizes = {
  82.     0x01: 3,
  83.     0x02: 3,
  84.     0x03: 3,
  85.     0x04: 3,
  86.     0x05: 1,
  87.     0x06: 2,
  88.     0x07: 11,
  89.     0x08: 12,
  90.     0x09: 1,
  91.     0x0A: 3,
  92.     0x0B: 4,
  93.     0x0C: 4,
  94.     0x0D: 1,
  95.     0x0E: 10,
  96.     0x0F: 2,
  97.  
  98.     0x15: 3,
  99.  
  100.     0x19: 4,
  101.  
  102.     0x1A: 3,
  103.  
  104.     0x1D: 3,
  105.  
  106.     0x1E: 21
  107. };
  108.  
  109. var server = {
  110.     info: new Server(info),
  111.     client: {},
  112.     isConnected: false
  113. };
  114.  
  115. var udpPort = 0;
  116. var udpCounter = 0;
  117. var udpTimers = [];
  118. var currentPlayerId = 3;
  119.  
  120. function connectFailed () {
  121.     //console.log('CONNECT FAILED');
  122.     server.isConnected = false;
  123.     udpTimers.forEach(clearInterval);
  124.     udp._handle && udp.close();
  125. };
  126.  
  127. function udpSend (data) {
  128.     data[3] = (udpCounter++) % 256;
  129.     data = udpchecksum(data);
  130.  
  131.     udp._handle && udp.send(data, 0, data.length, server.info.port, server.info.ip);
  132. };
  133.  
  134. function joinServer () {
  135.     /*if (server.info.address !== "80.78.215.117:10052") {
  136.         connectFailed();
  137.         return;
  138.     }*/
  139.  
  140.     //connectFailed();
  141.     //return;
  142.  
  143.     server.client.socketId = 0;
  144.     server.client.playerId = 0;
  145.     server.client.levelName = "";
  146.     server.client.isPlus = false;
  147.     server.client.players = [];
  148.  
  149.     server.client.game = {
  150.         gamemode: 0,
  151.         maxscore: 0,
  152.         customMode: 0,
  153.         ctf: {
  154.             teams: [
  155.                 {score: 0, holder: -1},
  156.                 {score: 0, holder: -1}
  157.             ]
  158.         },
  159.         time: {
  160.             started: false,
  161.             inPregame: false,
  162.             inOvertime: false,
  163.             timeLeft: 0,
  164.             time: 0,
  165.             autoCycle: false
  166.         },
  167.         isIdleserver: false,
  168.  
  169.     };
  170.     var game = server.client.game;
  171.  
  172.     server.client.lastTimeUpdate = Date.now();
  173.  
  174.     var password = "";
  175.    
  176.     var toSend = udpchecksum(new Buffer("yy"+"\x0A"+String.fromCharCode(password.length)+password));
  177.     udp.send(toSend, 0, toSend.length, server.info.port, server.info.ip);
  178.    
  179.     udp.on('message', function (data, rinfo) {
  180.         var olddata = data;
  181.         var packetId = data[2];
  182.         if (packetId === 0x02) {
  183.             var playercount = data[4];
  184.             var ids = [];
  185.            
  186.             for (var i = 0; i < playercount; i++) {
  187.                 var offset = 12*i;
  188.                 var playerId = data[offset+6] & 31;
  189.                 var health = data[offset+6] >> 5;
  190.                 ids.push(playerId);
  191.                
  192.                 var player = server.client.players[playerId];
  193.                 if (player) {
  194.                     player.xpos = (data[offset+10]+data[offset+11]*256)/32 % 1024;
  195.                     player.ypos = (data[offset+12]+data[offset+13]*256)/32 % 1024;
  196.                     player.health = health;
  197.                    
  198.                 } else {
  199.                     console.log("no player "+playerId);
  200.                 }
  201.             }
  202.             //console.log(playercount, ids);
  203.            
  204.            
  205.         } else if (packetId === 0x07) { // Subpacket/action
  206.             var i = 4;
  207.             var packets = [];
  208.             var ids = [];
  209.             //console.log(olddata.slice(4));
  210.            
  211.             while (i < data.length) {
  212.                 var id = data[i];
  213.                 //console.log(id);
  214.                 if (!actionSizes[id] || i+actionSizes[id]+1 > data.length) break;
  215.                 packets.push(data.slice(i, i+actionSizes[id]+1));
  216.                 i += actionSizes[id] + 1;
  217.                 ids.push(id);
  218.             }
  219.             /*if (Array.prototype.indexOf.call(data.slice(4), 0x0E) > -1) {
  220.                 console.log("UDP ACTION: ", Array.prototype.indexOf.call(data.slice(4), 0x0E), data.slice(4));
  221.                 console.log(ids);
  222.             }*/
  223.             //console.log(packets);
  224.            
  225.             for (var key = 0; key < packets.length; key++) {
  226.  
  227.                 var data = packets[key];
  228.  
  229.                 //console.log(data);
  230.                 var subPacketId = data[0];
  231.  
  232.                 //console.log(subPacketId);
  233.                 if (subPacketId === 0x03) { // Object destroyed/despawn
  234.  
  235.                 } else if (subPacketId === 0x04) { // Collision
  236.                    
  237.                     //sendChat("unknown packet");
  238.  
  239.                 } else if (subPacketId === 0x07) { // Bullet
  240.                     var gunman = ~~(data[6] / 4);
  241.                     var direction = (data[7] / 32) & 3;
  242.                     var weapon = data[7] % 16;
  243.                     var powered = Math.floor(data[7] / 128);
  244.                     var xpos = data.readUInt16LE(8) / 32;
  245.                     var ypos = data.readUInt16LE(10) / 32;
  246.                     //console.log('bullet', server.client.players[gunman].name, direction, zfs(data[7].toString(2), 8), data[7]);
  247.                     //sendChat("Bullet fired by "+server.client.players[gunman].name+" "+(weapon+1)+" "+(powered?'PU':''));
  248.                    
  249.                 } else if (subPacketId === 0x0C) { // Hurt
  250.                     var playerId = data[3] & 31;
  251.                     var health = data[3] >> 5;
  252.                     var player = server.client.players[playerId];
  253.                     if (player) {
  254.                         player.health = health;
  255.                     }
  256.  
  257.                 } else if (subPacketId === 0x0E) { // Roast/kill/suicide
  258.                     //console.log("ROAST");
  259.                     var i = 1;
  260.                     var victimId = data[i++];
  261.                     var victimPoints = data.readUInt32LE(i); i+=4;
  262.                     var killerId = data[i++];
  263.                     var killerPoints = data.readUInt32LE(i); i+=4;
  264.  
  265.                     var victim = server.client.players[victimId];
  266.                     var killer = server.client.players[killerId];
  267.  
  268.                     if (victim && killer) {
  269.                         //sendChat(killerPoints+", "+victimPoints);
  270.                        
  271.                         if (victimId !== killerId) {
  272.                             killer.points = killerPoints;
  273.                             victim.points = victimPoints;
  274.                            
  275.                             //sendChat(killer.name+" roasted "+victim.name);
  276.                             //sendChat(killer.name+' got '+killer.points+' points');
  277.                             //sendChat(victim.name+' got '+victim.points+' points');
  278.                         } else {
  279.                             killer.points = killerPoints;
  280.                             //sendChat(killer.name+" ate it");
  281.                             //sendChat(killer.name+' got '+killer.points+' points');
  282.                         }
  283.  
  284.                     } else {
  285.                         //sendChat("Unknown killer/victim player.", killerId, victimId);
  286.                     }
  287.  
  288.                 } else if (subPacketId === 0x0F) { // Streetfightad
  289.                     var victimId = data[1] & 31;
  290.                     var victimHealth = data[1] >> 5;
  291.                     var killerId = data[2];
  292.  
  293.                     var victim = server.client.players[victimId];
  294.                     var killer = server.client.players[killerId];
  295.  
  296.                     if (victim && killer) {
  297.                         //sendChat(killer.name+" streetfighted "+victim.name);
  298.                     } else {
  299.                         //sendChat(killerId+" streetfighted "+victimId);
  300.                     }
  301.                     if (victim) {
  302.                         victim.health = health;
  303.                     }
  304.                     /*var toSend = new Buffer(11);
  305.                     toSend[2] = 0x07;
  306.                     toSend[4] = 0x0F;
  307.                     toSend[5] = killerId;
  308.                     toSend[6] = victimId;
  309.                     //console.log(olddata);
  310.                     //udpSend(toSend);
  311.                     console.log(toSend);*/
  312.                    
  313.  
  314.                 } else if (subPacketId === 0x15) {
  315.  
  316.                 } else if (subPacketId === 0x1E) {
  317.                     //console.log(data);
  318.                     var bluescore = data[5];
  319.                     var redscore = data[10];
  320.                     var blueHolder = data[20] > 0 ? data[21] : -1;
  321.                     var redHolder = data[17] > 0 ? data[18] : -1;
  322.  
  323.                     game.ctf.teams[0].score = bluescore;
  324.                     game.ctf.teams[1].score = redscore;
  325.                     game.ctf.teams[0].holder = blueHolder;
  326.                     game.ctf.teams[1].holder = redHolder;
  327.  
  328.                     //console.log('score: ', bluescore, redscore, 'holder: ', blueHolder, redHolder);
  329.                 } else {
  330.                     //console.log("GOT ACTION UDP", "0x"+subPacketId.toString(16), data);
  331.                 }
  332.  
  333.             }
  334.  
  335.            
  336.         } else if (packetId === 0x09) { // Keep alive (JJ2+)
  337.             var toSend = data;
  338.             udpSend(toSend);
  339.            
  340.         } else if (packetId === 0x0B) {
  341.             if (data[3] > 0) {
  342.                 startTCP();
  343.             } else if (password) {
  344.                 //console.log("Wrong password '"+password+"' for "+server.info.servername);
  345.             }
  346.         } else {
  347.             //console.log("UDP", data)
  348.         }
  349.        
  350.        
  351.     });
  352.  
  353.     var extraPlusData = new Buffer(0);
  354.  
  355.     var sendChat = function (msg) {
  356.         if(server.client.socketId) {
  357.             var toSend = "\x1B"+String.fromCharCode(server.client.socketId)+"\x20"+msg;
  358.             toSend = String.fromCharCode(toSend.length+1)+toSend;
  359.             if(conn.client._handle) {
  360.                 conn.client.write(new Buffer(toSend, "binary"));
  361.                 return true;
  362.             }
  363.         }
  364.         return false;
  365.     };
  366.  
  367.     var getPlayerId = function (sock) {
  368.         var result = [];
  369.         for(var i=0; i < server.client.players.length; i+=1) {
  370.             if(server.client.players[i] !== undefined && server.client.players[i].socketId === sock) {
  371.                 result.push(i);
  372.             }
  373.         }
  374.         return result;
  375.     };
  376.  
  377.     function sendUpdateRequest() {
  378.         // update request
  379.         toSend = new Buffer(6);
  380.         toSend[0] = 6;
  381.         toSend[1] = 0x1A;
  382.         extraPlusData.copy(toSend, 2, 0, 4);
  383.         conn.client.write(toSend);
  384.         console.log("Sent update request");
  385.     }
  386.  
  387.     function startGame() {
  388.         // udp handshake
  389.         var toSend = new Buffer(8);
  390.         toSend[2] = 0x09;
  391.         toSend[3] = server.client.socketId;
  392.         extraPlusData.copy(toSend, 4, 4, 8);
  393.         udpSend(toSend);
  394.  
  395.         //client.write("\x03\x42\x21", 'binary'); // Make bot spectate
  396.  
  397.         server.isConnected = true; // Important
  398.  
  399.         var startTime = Date.now();
  400.  
  401.         udpTimers.push(setInterval(function () {
  402.             var myPlayer = server.client.players[server.client.playerId];
  403.             var followPlayer = server.client.players[currentPlayerId] || server.client.players[0];
  404.  
  405.             if (myPlayer.health === 0) {
  406.                 myPlayer.xpos = 0;
  407.                 myPlayer.ypos = 0;
  408.                 myPlayer.health = 5;
  409.             }
  410.  
  411.             var time = (Date.now()/1000)*2;
  412.  
  413.             var x = followPlayer.xpos+3*Math.cos(time);
  414.             var y = followPlayer.ypos+3*Math.sin(time*0.6);
  415.  
  416.             var dx = myPlayer.xpos-x;
  417.             var dy = myPlayer.ypos-y;
  418.  
  419.             var distance = Math.min(Math.sqrt(dx*dx+dy*dy)/10, 1.5);
  420.  
  421.             //console.log(dx, dy, distance);
  422.             var angle = Math.atan2(dy, dx);
  423.             //console.log(~~(angle*57.2957795), ~~(dx/32), ~~(dy/32), 10*Math.cos(angle), 10*Math.sin(angle), ~~distance);
  424.            
  425.             var velx = -distance*Math.cos(angle);
  426.             var vely = -distance*Math.sin(angle);
  427.  
  428.             myPlayer.xpos += velx;
  429.             myPlayer.ypos += vely;
  430.             myPlayer.xpos = Math.max(0, Math.min(myPlayer.xpos, 1024));
  431.             myPlayer.ypos = Math.max(0, Math.min(myPlayer.ypos, 1024));
  432.  
  433.             //console.log(~~velx*32, ~~vely*32);
  434.  
  435.             myPlayer.direction = velx > 0;
  436.  
  437.             var xpos = new Buffer(new Uint8Array(new Uint16Array([myPlayer.xpos*32]).buffer));
  438.             var ypos = new Buffer(new Uint8Array(new Uint16Array([myPlayer.ypos*32]).buffer));
  439.  
  440.             var toSend = new Buffer([0, 0, 0x01, 0, 0x01, Math.floor(Date.now()/70)%256, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  441.  
  442.             toSend[2+7] = xpos[0];
  443.             toSend[3+7] = (xpos[1] & 0x7F) | (myPlayer.direction*0x80);
  444.             toSend[4+7] = ypos[0];
  445.             toSend[5+7] = ypos[1];
  446.             toSend[6+7] = 67;//Math.floor(Date.now()/500) % 128; // 67, 77
  447.             toSend[7+7] = Math.floor(Date.now()/70) % 12;
  448.  
  449.             if (vely < -0.25) {
  450.                 toSend[6+7] = 70; // swim up
  451.             } else if (vely > 0.4) {
  452.                 toSend[6+7] = 66; // swim down
  453.             }
  454.  
  455.  
  456.             udpSend(toSend);
  457.  
  458.  
  459.         }, 1000/20));
  460.  
  461.         udpTimers.push(setInterval(function () {
  462.  
  463.             var myPlayer = server.client.players[server.client.playerId];
  464.  
  465.             //var xpos = new Buffer(new Uint8Array(new Uint16Array([myPlayer.xpos*32]).buffer));
  466.             //var ypos = new Buffer(new Uint8Array(new Uint16Array([myPlayer.ypos*32]).buffer));
  467.  
  468.             var weapon = 0; // zero based
  469.             var direction = myPlayer.direction ? 1 : 0;
  470.             var powered = false;
  471.  
  472.             var toSend = new Buffer(5+11);
  473.             toSend.fill(0);
  474.             toSend[2] = 0x08;
  475.             toSend[4] = 0x07;
  476.             toSend[8] = 0x07;
  477.             toSend[9] = server.client.playerId;
  478.             toSend[10] = server.client.playerId*4;
  479.             toSend[11] = (powered << 7) | (direction << 5) | weapon;
  480.             toSend.writeUInt16LE(myPlayer.xpos*32|0, 12);
  481.             toSend.writeUInt16LE(myPlayer.ypos*32|0, 14);
  482.             //udpSend(toSend);
  483.         }, 500));
  484.     }
  485.  
  486.     function downloadFiles(cb) {
  487.         console.log("Downloading "+server.client.levelName);
  488.  
  489.         //var toSend = chr(levelFileName.length+3)+"\x15"+chr(levelFileName.length)+levelFileName;
  490.         var toSend = new Buffer(server.client.levelName.length+3);
  491.         toSend[0] = toSend.length;
  492.         toSend[1] = 0x15;
  493.         toSend[2] = server.client.levelName.length;
  494.         toSend.write(server.client.levelName, 3, server.client.levelName.length, 'binary');
  495.         console.log(toSend, toSend.toString('binary'));
  496.         //conn.client.write(toSend);
  497.  
  498.         // When finished downloading
  499.         sendUpdateRequest();
  500.         if (typeof cb === 'function') cb();
  501.        
  502.     }
  503.  
  504.     function startTCP () {
  505.         var client = net.connect(server.info.port, server.info.ip);
  506.         conn.client = client;
  507.  
  508.         client.on('connect', function () {
  509.             clearTimeout(clientTimer);
  510.             console.log('connected to '+server.info.address);
  511.  
  512.             var buf = new Buffer(9);
  513.             buf.write("\x09\x0F", 0, 'binary');
  514.             buf.writeUInt16LE(udpPort, 2);
  515.             server.info.version.copy(buf, 4);
  516.             buf.write("\x01", 8, 'binary');
  517.             client.write(buf);
  518.  
  519.         });
  520.         client.on('data', function (res) {
  521.            
  522.  
  523.             // TODO: Clean up the code!
  524.             var p = 0, j = res.length, res_a = [], l = 0;
  525.             var special = false;
  526.             while (p < j) {
  527.                
  528.                 l = res[p];
  529.                
  530.                 if (res[p] === 0 && ++p < j) {
  531.                     l = res.readUInt16LE(p);
  532.                     p += 2;
  533.                     var buf = new Buffer(l+1);
  534.                     buf[0] = 0;
  535.                     res.copy(buf, 1, p, p+l);
  536.                     res_a.push(buf);
  537.                    
  538.                 } else {
  539.                     if (p+l > j) {
  540.                         //console.log('oob', p, l, j, res);
  541.                         break;
  542.                     }
  543.                     res_a.push(res.slice(p, p+l));
  544.                 }
  545.                 p += l;
  546.             }
  547.  
  548.             for (var key = 0; key < res_a.length; key++) { // Loops through packet array
  549.                 var data = res_a[key];
  550.  
  551.                 var packetId = data[1];
  552.  
  553.                 if (packetId === 0x0D) { // Disconnect
  554.                     //console.log(data);
  555.  
  556.                     var type = data[2];
  557.                     var message = disconnectMessages[type] || ("Unknown error |"+type);
  558.  
  559.                     var playerid = getPlayerId(data[3]);
  560.                     var reason = data.length > 10 ? data.slice(10).toString('binary') : "";
  561.                     //console.log("Disconnected:", data[3], type, message, reason && "("+reason+")");
  562.                     for(var i = 0; i < playerid.length; i++) {
  563.                         if(type !== 7) {
  564.                             sendChat("ยง1"+server.client.players[playerid[i]].name+" left: |"+message +" |"+(reason && "("+reason+")"));
  565.                         }
  566.                         if (playerid[i] === server.client.playerId) {
  567.                             console.log("The bot was disconnected from", server.info.address, server.info.servername, message, reason && "("+reason+")");
  568.                         }
  569.                         delete server.client.players[playerid[i]];
  570.                     }
  571.  
  572.  
  573.                 } else if (packetId === 0x10) { // Server info
  574.  
  575.                     var i = 2;
  576.                     server.client.socketId = data[i++];
  577.                     server.client.playerId = data[i++];
  578.                     var l = data[i++];
  579.                     server.client.levelName = data.slice(i, i + l).toString('binary');
  580.                     i += l;
  581.                    
  582.                     i+=8; // Skip CRC stuff
  583.                     server.client.game.gamemode = data[i++];
  584.                     server.client.game.maxscore = data[i++];
  585.                    
  586.                     if (data.length > i) {
  587.                         extraPlusData = data.slice(i);
  588.                     } else {
  589.                         client.destroy();
  590.                         connectFailed();
  591.                         return;
  592.                     }
  593.                     //console.log(extraPlusData);
  594.                    
  595.                     client.write("\x08\x3F\x20\x01\x00\x00\x04\x01"); // JJ2+ New
  596.  
  597.  
  598.                     //console.log("info?!1+", data.slice(i));
  599.  
  600.                     var toSend = "\x0E\x01"+String.fromCharCode(server.client.playerId)+"\x02\x00"+"\x18\x10\x28\x20"+BOT_NAME+"\x00";
  601.                     toSend = String.fromCharCode(toSend.length+1)+toSend;
  602.                     client.write(toSend, 'binary');
  603.                 } else if(packetId === 0x11) { // Someone joins...
  604.                     var packetLength = data.length;
  605.                     var i=4; // Skip player amount
  606.                     var sockID = data[2];
  607.                     var playerid;
  608.                     var pname = "";
  609.                     var fur;
  610.                     var charTeam;
  611.                     while(packetLength>i) {
  612.                         playerid = data[i++];
  613.                         charTeam = data[i++];
  614.                         i++;
  615.                         fur = [data[i++], data[i++], data[i++], data[i++]];
  616.                         pname = "";
  617.                         while(data[i] != undefined) {pname+=String.fromCharCode(data[i++]);if(data[i]==0) break;}
  618.                         i+=1;
  619.                         server.client.players[playerid] = {
  620.                             charTeam: charTeam,
  621.                             fur: fur,
  622.                             name: pname,
  623.                             socketId: sockID,
  624.                             spectating: false,
  625.                             points: 0,
  626.                             deaths: 0,
  627.                             ping: -1,
  628.                             xpos: 0,
  629.                             ypos: 0,
  630.                             direction: true,
  631.                             health: 5
  632.                         };
  633.                     }
  634.                 } else if(packetId === 0x12) { // Playerlist
  635.                     var packetLength = data.length;
  636.                     var totalplayers = 0;
  637.                     var i = 3;
  638.                     while (packetLength>i) {
  639.                         var psock = data[i++];
  640.                         var pplayer = data[i++];
  641.                         var pcharTeam = data[i++];
  642.                         i++;
  643.                        
  644.                         var fur = [data[i++], data[i++], data[i++], data[i++]];
  645.                         var pname = "";
  646.                         while(data[i] != undefined) {pname+=String.fromCharCode(data[i++]);if(data[i]==0) break;}
  647.                         i += 1;
  648.                         totalplayers += 1;
  649.                         if (!server.client.players[pplayer]) {
  650.                             server.client.players[pplayer] = {
  651.                                 spectating: false,
  652.                                 points: 0,
  653.                                 deaths: 0,
  654.                                 ping: -1
  655.                             };
  656.                         }
  657.  
  658.                         var player = server.client.players[pplayer];
  659.                         player.name = pname;
  660.                         player.fur = fur;
  661.                         player.charTeam = pcharTeam;
  662.                         player.socketId = psock;
  663.                         player.xpos = 0;
  664.                         player.ypos = 0;
  665.                         player.direction = true;
  666.                         player.health = 5;
  667.                        
  668.                        
  669.                         //roomBroadcast(JSON.stringify({'console': [(pplayer+1)+". "+pname, 1]}), roomId);
  670.                    
  671.                     }
  672.                     //console.log(server.client.players);
  673.                     //roomBroadcast(JSON.stringify({'console': [Array.prototype.slice.call(data, 2).join(" "), 1]}), roomId);
  674.                    
  675.                 } else if (packetId === 0x13) { // Game init
  676.  
  677.                     if (server.isConnected) {
  678.                         continue;
  679.                     }
  680.  
  681.                     downloadFiles(startGame);
  682.  
  683.                     // ??
  684.                     //udp.send(new Buffer([0x0A, 0x15, 0x09, 0x00 ]), 0, 4, server.info.port, server.info.ip);
  685.  
  686.                 } else if (packetId === 0x14) {
  687.                     var index = 2;
  688.                     var currPieceID = data.readUInt32LE(index); // LATEST PLUS ONLY!
  689.                     index += 4;
  690.                     if (currPieceID === 0) {
  691.                         var expectedDownloadFileSize = data.readUInt32LE(index); // filesize
  692.                     }
  693.  
  694.  
  695.                 } else if(packetId === 0x16) { // Level cycle
  696.                     var i = 2;
  697.                     i+=8; // Skip CRC stuff
  698.                     var l = data[i++];
  699.                     server.client.levelName = data.slice(i, i + l - 1).toString('binary');
  700.                     i += l;
  701.                    
  702.                    
  703.                     extraPlusData = data.slice(i);
  704.                    
  705.                     downloadFiles();
  706.                    
  707.  
  708.                     // udp
  709.                     /*var toSend = new Buffer(4);
  710.                     toSend[2] = 0x09;
  711.                     udpSend(toSend);*/
  712.  
  713.                     for (var i = 0; i < server.client.players.length; i++) {
  714.                         var player = server.client.players[i];
  715.                         if (player) {
  716.                             player.points = 0;
  717.                             player.deaths = 0;
  718.                             //console.log("Reset points/deaths for "+player.name);
  719.  
  720.                         }
  721.                     }
  722.                    
  723.                 } else if (packetId === 0x17) { // End of level
  724.                    
  725.                 } else if (packetId === 0x18) { // Events update
  726.                    
  727.                 } else if (packetId === 0x1B) { // Chat
  728.                     var message = data.slice(4).toString('binary');
  729.                     var playerId = getPlayerId(data[2])[0];
  730.                     var player = server.client.players[playerId];
  731.                     if (message === "!follow") {
  732.                         if (player) {
  733.                             currentPlayerId = playerId;
  734.                             sendChat("Now following "+player.name);
  735.                         } else {
  736.                             sendChat("Player "+(playerId+1)+" not found");
  737.                         }
  738.                     }
  739.                    
  740.                 } else if (packetId === 0x3F) { // Plus packet
  741.                     game.customMode = data[6];
  742.                 } else if (packetId === 0x40) { // Console message
  743.                     //console.log("Console: "+data.slice(3).toString('binary'));
  744.                 } else if (packetId === 0x41) {
  745.                     //console.log("SPECTATE", data.slice(2));
  746.                     //sendChat('got spectate packet: '+data[2].toString(2)+' ['+Array.prototype.slice.call(data, 2).join(", ")+']');
  747.                     var i = 2;
  748.                     var spectatePacketType = data[i++];
  749.                     if (spectatePacketType === 0) {
  750.                         //sendChat("zepectate: "+data[i++].toString(2)+" "+data[i++].toString(2)+" ["+Array.prototype.slice.call(data, 2).join(", ")+']');
  751.                         var unknown = data[i++];
  752.                         var binary = data[i++];
  753.                         for (var i = 0; i < server.client.players.length; i++) {
  754.                             var player = server.client.players[i];
  755.                             if (player) {
  756.                                 var isSpec = ((binary >> player.socketId) & 1) === 1;
  757.                                 if (isSpec !== player.spectating) {
  758.                                     if (isSpec) {
  759.                                         //sendChat(player.name+" is now spectating");
  760.                                         player.points = 0;
  761.                                         player.deaths = 0;
  762.                                         //console.log("Reset points/deaths for "+player.name);
  763.  
  764.                                     } else {
  765.                                         //sendChat(player.name+" is no longer spectating");
  766.                                     }
  767.                                     player.spectating = isSpec;
  768.                                 }
  769.                             }
  770.  
  771.                         }
  772.  
  773.                     } else if (spectatePacketType === 1) {
  774.                         var spectateType = data[i++];
  775.                         var clientId = data[i++];
  776.                         var spectateId = data[i++];
  777.                         var playerIds = getPlayerId(clientId);
  778.                        
  779.                         //console.log("someone changed spec", data);
  780.                         var isSpec = spectateId !== 0xFE;
  781.                         for (var i = 0; i < playerIds.length; i++) {
  782.                             var player = server.client.players[playerIds[i]];
  783.                            
  784.                             if (player && isSpec !== player.spectating) {
  785.                                 if (isSpec) {
  786.                                     //sendChat(player.name+" is spectating");
  787.                                     player.points = 0;
  788.                                     player.deaths = 0;
  789.                                 } else {
  790.                                     //sendChat(player.name+" is no longer spectating");
  791.                                 }
  792.                                 player.spectating = isSpec;
  793.                             }
  794.                            
  795.                         }
  796.                     }
  797.                     /*if(data[0] === 5) {
  798.                         console.log("got spec list: "+data[2].toString(2), data.slice(3));
  799.                         //sendChat('got spec list: '+data[2].toString(2)+' ['+Array.prototype.slice.call(data, 2)+']');
  800.                         var binary = data[2];
  801.                         for (var i = 0; i < server.client.players.length; i++) {
  802.                             var player = server.client.players[i];
  803.                             if (player) {
  804.                                 var isSpec = ((binary >> player.socketId) & 1) === 1;
  805.                                 console.log(isSpec, player.spectating)
  806.                                 if (isSpec !== player.spectating) {
  807.                                     if (isSpec) {
  808.                                         sendChat(player.name+" is spectating");
  809.                                     } else {
  810.                                         sendChat(player.name+" is no longer spectating");
  811.                                     }
  812.                                     player.spectating = isSpec;
  813.                                 }
  814.                             }
  815.  
  816.                         }
  817.                     }
  818.                     else {
  819.                         var playerIds = getPlayerId(data[2]);
  820.                        
  821.                         //console.log("someone changed spec", data);
  822.                         var isSpec = data[3] !== 0xFE;
  823.                         for (var i = 0; i < playerIds.length; i++) {
  824.                             var player = server.client.players[playerIds[i]];
  825.                            
  826.                             if (player && isSpec !== player.spectating) {
  827.                                 if (isSpec) {
  828.                                     sendChat(player.name+" is spectating");
  829.                                 } else {
  830.                                     sendChat(player.name+" is no longer spectating");
  831.                                 }
  832.                                 player.spectating = isSpec;
  833.                             }
  834.                            
  835.                         }
  836.                        
  837.                     }*/
  838.                 } else if (packetId === 0x45) { // Time
  839.                     var gameState = data[2];
  840.                     var gameStarted = !!(gameState & 1);
  841.                     var inPregame = !((gameState >> 1) & 1) && ((gameState >> 2) & 1);
  842.                     var inOvertime = !!(((gameState >> 1) & 1) && ((gameState >> 2) & 1));
  843.                     var timeLeft = data.readUInt32LE(3)/1000;
  844.                     var mins = Math.floor(timeLeft / 60);
  845.                     var secs = Math.floor(timeLeft) % 60;
  846.  
  847.                     game.time.started = gameStarted;
  848.                     game.time.autoCycle =  !!((gameState >> 1) & 1);
  849.                     game.time.inPregame = inPregame;
  850.                     game.time.inOvertime = inOvertime;
  851.                     game.time.timeLeft = timeLeft;
  852.  
  853.                     server.client.lastTimeUpdate = Date.now();
  854.                     //console.log(timeLeft);
  855.                     //sendChat("ยง0|"+(gameStarted?(inPregame?"|||":"")+(inOvertime?"||":""):"|")+zfs(mins)+":"+zfs(secs)+" left");
  856.  
  857.                 } else if (packetId === 0x49) { // Pings
  858.                     //sendChat("Pings: "+Array.prototype.slice.call(data, 2).join(", "));
  859.                     var i = 2;
  860.                     while (i < data.length) {
  861.                         var playerId = data[i++];
  862.                         var ping = data.readUInt16LE(i); i+=2;
  863.                         var player = server.client.players[playerId];
  864.                         if (player) {
  865.                             player.ping = ping;
  866.                         }
  867.                     }
  868.  
  869.                 } else if (packetId === 0x4A) { // Gamemode and maxscore
  870.                     var gamemode = data[2];
  871.                     var customGamemode = data[3];
  872.                     var maxscore = data[4];
  873.                     game.gamemode = gamemode;
  874.                     game.maxscore = maxscore;
  875.                     game.customMode = customGamemode;
  876.                     //console.log(customGamemode > 0 ? "Custom gamemode: "+customGamemode : "Gamemode: "+gamemode, "maxscore: "+maxscore)
  877.                 } else if (packetId === 0x4C) { // Player stats
  878.                    
  879.                     var i = 2, len = data.length;
  880.                     while (i < len) {
  881.                         var playerId = data[i++];
  882.                         var points = data.readUInt32LE(i); i += 4;
  883.                         var deaths = data.readUInt32LE(i); i += 4;
  884.                         var player = server.client.players[playerId];
  885.                         if (player) {
  886.                             player.points = points;
  887.                             player.deaths = deaths;
  888.                             //sendChat(player.name+' got '+player.points+' points and '+player.deaths+' deaths');
  889.                         } else {
  890.                             sendChat("Unknown player "+playerId);
  891.                         }
  892.                     }
  893.  
  894.                 } else if (packetId === 0x4D) { // Deaths
  895.                     //sendChat(Array.prototype.slice.call(data, 2).join(", "));
  896.                     var i = 2, len = data.length;
  897.                     while (i < len) {
  898.                         var playerId = data[i++];
  899.                         var deaths = data.readUInt32LE(i); i += 4;
  900.                         var player = server.client.players[playerId];
  901.                         if (player) {
  902.                             player.deaths = deaths;
  903.                             //sendChat(player.name+' got '+player.deaths+' deaths');
  904.                         } else {
  905.                             sendChat("Unknown player "+playerId);
  906.                         }
  907.                     }
  908.                 } else if (packetId === 0x50) { // TCP_SC_MISC
  909.  
  910.                 } else if (packetId === 0x52) { // Idleserver
  911.                     game.isIdleserver = !!data[2];
  912.                     //sendChat("IDLESERVER IS "+(isIdleserver? "|ENABLED" : "||DISABLED"));
  913.                    
  914.                 } else {
  915.                     //console.log("TCP: 0x"+packetId.toString(16), data.slice(2));
  916.                 }
  917.                
  918.                 //console.log("0x"+packetId.toString(16));
  919.                
  920.             }
  921.         });
  922.         client.on('error', function (err) {
  923.             console.log("client "+err);
  924.         });
  925.         client.on('close', function () {
  926.             console.log('Disconnected from', server.info.address, server.info.servername);
  927.             connectFailed();
  928.         });
  929.         var clientTimer = setTimeout(function () {
  930.             client.destroy();
  931.         }, 3000);
  932.  
  933.     }
  934. };
  935.  
  936. var conn = {};
  937.  
  938. var query = udpchecksum(new Buffer("yy\x05\x00"));
  939. conn.udp = dgram.createSocket("udp4");
  940. var udp = conn.udp;
  941.  
  942. var isFirst = true;
  943. udp.on('listening', function () {
  944.     var rinfo = udp.address();
  945.     //console.log("Listening on "+rinfo.address+":"+rinfo.port);
  946.  
  947.     udpPort = rinfo.port;
  948.     udp.send(query, 0, query.length, server.info.port, server.info.ip);
  949. });
  950. udp.on('message', function (data, rinfo) {
  951.    
  952.     if (rinfo.address === server.info.ip && rinfo.port === server.info.port && isFirst) {
  953.         isFirst = false;
  954.         clearTimeout(queryTimer);
  955.  
  956.         server.info.version = data.slice(8, 8+4);
  957.         server.info.capacity = [data[12], data[15]];
  958.         server.info.gametype = data[14];
  959.         server.info.servername = data.slice(17, 17+data[16]).toString('binary');
  960.  
  961.         joinServer();
  962.     }
  963. });
  964. udp.on('error', function (err) {
  965.     console.log('UDP '+err)
  966. });
  967. udp.bind();
  968. var queryTimer = setTimeout(function () {
  969.     conn.udp.close();
  970.     connectFailed();
  971. }, 3000);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement