Advertisement
djazz

SGIP BOT (For extra info)

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