From 788b738603c4a5f9b7ecaa4795fdc28b84799b66 Mon Sep 17 00:00:00 2001 From: Sang Hero Date: Sat, 19 Mar 2016 14:01:38 +0700 Subject: [PATCH 1/3] NEXT-5 Integrate agario-client to NEXT --- client/js/agario-client/Account.js | 108 +++++ client/js/agario-client/Ball.js | 115 +++++ client/js/agario-client/Packet.js | 187 ++++++++ client/js/agario-client/client.js | 670 +++++++++++++++++++++++++++++ client/js/agario-client/servers.js | 157 +++++++ client/js/controller.js | 11 +- client/js/main.js | 10 +- config.js | 267 +----------- gulpfile.js | 3 + package.json | 56 ++- 10 files changed, 1289 insertions(+), 295 deletions(-) create mode 100644 client/js/agario-client/Account.js create mode 100644 client/js/agario-client/Ball.js create mode 100644 client/js/agario-client/Packet.js create mode 100644 client/js/agario-client/client.js create mode 100644 client/js/agario-client/servers.js diff --git a/client/js/agario-client/Account.js b/client/js/agario-client/Account.js new file mode 100644 index 0000000..9c4f01c --- /dev/null +++ b/client/js/agario-client/Account.js @@ -0,0 +1,108 @@ +'use strict'; + +import https from 'https'; +import EventEmitter from 'events'; + +const agarClientId = '677505792353827'; //hardcoded in client + +export default class Account { + + constructor(name) { //todo doc vars + this.name = name; //debug name + this.token = null; //token after requestFBToken() + this.token_expire = 0; //timestamp after requestFBToken() + this.token_provider = 1; //provider ID after requester + this.c_user = null; //cookie from www.facebook.com + this.datr = null; //cookie from www.facebook.com + this.xs = null; //cookie from www.facebook.com + this.agent = null; //connection agent + this.debug = 1; + this.server = 'wss://web-live-v3-0.agario.miniclippt.com/ws'; //todo doc + + this.ws = null; + } + + log(text) { + if (this.name) { + console.log('Account(' + this.name + '): ' + text); + } else { + console.log('Account: ' + text); + } + } + + requestFBToken(cb) { + var account = this; + + if (this.debug >= 1) { + if (!this.c_user) this.log('[warning] You did not specified Account.c_user'); + if (!this.datr) this.log('[warning] You did not specified Account.datr'); + if (!this.xs) this.log('[warning] You did not specified Account.xs'); + } + + var ret = { + error: null, + res: null, + data: null, + }; + + var cUser = this.c_user; + var datr = this.datr; + var xs = this.xs; + + //Some users don't decode their cookies, so let's try do it here + if (cUser && cUser.indexOf('%')) cUser = decodeURIComponent(cUser); + if (datr && datr.indexOf('%')) datr = decodeURIComponent(datr); + if (xs && xs.indexOf('%')) xs = decodeURIComponent(xs); + + var cookies = 'c_user=' + encodeURIComponent(cUser) + ';' + + 'datr=' + encodeURIComponent(datr) + ';' + + 'xs=' + encodeURIComponent(xs) + ';'; + + var options = { + host: 'www.facebook.com', + path: '/dialog/oauth?client_id=' + agarClientId + '&redirect_uri=https://agar.io&scope=public_profile,%20email&response_type=token', + method: 'GET', + headers: { + 'User-Agent': 'Mozilla/5.0', + Cookie: cookies, + }, + agent: this.agent || null, + }; + + var req = https.request(options, function(res) { + var data = ''; + ret.res = res; + + res.setEncoding('utf8'); + res.on('data', function(chunk) { + data += chunk; + }); + res.on('end', function() { + ret.data = data; + + if (res && res.headers && res.headers.location) { + res.headers.location.replace(/access_token=([a-zA-Z0-9-_]*)&/, function(_, parsed_token) { + if (parsed_token) { + account.token = parsed_token; + account.token_provider = 1; + } + }); + res.headers.location.replace(/expires_in=([0-9]*)/, function(_, expire) { + if (expire) { + account.token_expire = Date.now() + expire * 1000; + } + }); + } + + if (cb) cb(account.token, ret); + }); + }); + + req.on('error', function(e) { + ret.error = e; + if (cb) cb(null, ret); + }); + + req.end(); + } +} diff --git a/client/js/agario-client/Ball.js b/client/js/agario-client/Ball.js new file mode 100644 index 0000000..aecef68 --- /dev/null +++ b/client/js/agario-client/Ball.js @@ -0,0 +1,115 @@ +'use strict'; + +export default class Ball { + + constructor(client, id) { + if (client.balls[id]) return client.balls[id]; + + this.id = id; + this.name = null; + this.x = 0; + this.y = 0; + this.size = 0; + this.mass = 0; + this.virus = false; + this.mine = false; + + this.client = client; + this.destroyed = false; + this.visible = false; + this.last_update = Date.now(); + this.update_tick = 0; + + client.balls[id] = this; + return this; + } + + destroy(reason) { + this.destroyed = reason; + delete this.client.balls[this.id]; + var mine_ball_index = this.client.my_balls.indexOf(this.id); + if (mine_ball_index > -1) { + this.client.my_balls.splice(mine_ball_index, 1); + this.client.emitEvent('mineBallDestroy', this.id, reason); + if (!this.client.my_balls.length) this.client.emitEvent('lostMyBalls'); + } + + this.emitEvent('destroy', reason); + this.client.emitEvent('ballDestroy', this.id, reason); + } + + setCords(new_x, new_y) { + if (this.x == new_x && this.y == new_y) return; + var old_x = this.x; + var old_y = this.y; + this.x = new_x; + this.y = new_y; + + if (!old_x && !old_y) return; + this.emitEvent('move', old_x, old_y, new_x, new_y); + this.client.emitEvent('ballMove', this.id, old_x, old_y, new_x, new_y); + } + + setSize(new_size) { + if (this.size == new_size) return; + var old_size = this.size; + this.size = new_size; + this.mass = parseInt(Math.pow(new_size / 10, 2)); + + if (!old_size) return; + this.emitEvent('resize', old_size, new_size); + this.client.emitEvent('ballResize', this.id, old_size, new_size); + if (this.mine) this.client.updateScore(); + } + + setName(name) { + if (this.name == name) return; + var old_name = this.name; + this.name = name; + + this.emitEvent('rename', old_name, name); + this.client.emitEvent('ballRename', this.id, old_name, name); + } + + update() { + var old_time = this.last_update; + this.last_update = Date.now(); + + this.emitEvent('update', old_time, this.last_update); + this.client.emitEvent('ballUpdate', this.id, old_time, this.last_update); + } + + appear() { + if (this.visible) return; + this.visible = true; + this.emitEvent('appear'); + this.client.emitEvent('ballAppear', this.id); + + if (this.mine) this.client.updateScore(); + } + + disappear() { + if (!this.visible) return; + this.visible = false; + this.emitEvent('disappear'); + this.client.emitEvent('ballDisppear', this.id); + } + + toString() { + if (this.name) return this.id + '(' + this.name + ')'; + return this.id.toString(); + } + + // Fix https://github.com/pulviscriptor/agario-client/issues/95 + emitEvent() { + var args = []; + for (var i = 0; i < arguments.length; i++) args.push(arguments[i]); + try { + this.emit.apply(this, args); + } catch (e) { + process.nextTick(function() { + throw e; + }); + } + } +} diff --git a/client/js/agario-client/Packet.js b/client/js/agario-client/Packet.js new file mode 100644 index 0000000..a964889 --- /dev/null +++ b/client/js/agario-client/Packet.js @@ -0,0 +1,187 @@ +'use strict'; + +export default class Packet { + + constructor(e) { + if (e instanceof Buffer) { + this.data = e; + this.length = this.data.length; + } else if ((typeof Buffer) != 'undefined' && e.data instanceof Buffer) { + this.data = e.data; + this.length = this.data.length; + } else { + this.data = new DataView(e.data); + this.length = this.data.byteLength; + } + + this.offset = 0; + } + + readUInt8(p) { + var offset = (typeof p) == 'number' ? p : this.offset; + var ret; + if (this.data.getUint8) { + ret = this.data.getUint8(offset); + } else { + ret = this.data.readUInt8(offset); + } + if (p === undefined) this.offset += 1; + + return ret; + } + + readUInt16BE(p) { + var offset = (typeof p) == 'number' ? p : this.offset; + var ret; + if (this.data.getUint16) { + ret = this.data.getUint16(offset, false); + } else { + ret = this.data.readUInt16BE(offset); + } + if (p === undefined) this.offset += 2; + + return ret; + } + + readUInt16LE(p) { + var offset = (typeof p) == 'number' ? p : this.offset; + var ret; + if (this.data.getUint16) { + ret = this.data.getUint16(offset, true); + } else { + ret = this.data.readUInt16LE(offset); + } + if (p === undefined) this.offset += 2; + + return ret; + } + + readSInt16LE(p) { + var offset = (typeof p) == 'number' ? p : this.offset; + var ret; + if (this.data.getInt16) { + ret = this.data.getInt16(offset, true); + } else { + ret = this.data.readInt16LE(offset); + } + if (p === undefined) this.offset += 2; + + return ret; + } + + readUInt32LE(p) { + var offset = (typeof p) == 'number' ? p : this.offset; + var ret; + if (this.data.getUint32) { + ret = this.data.getUint32(offset, true); + } else { + ret = this.data.readUInt32LE(offset); + } + if (p === undefined) this.offset += 4; + + return ret; + } + + readUInt32BE(p) { + var offset = (typeof p) == 'number' ? p : this.offset; + var ret; + if (this.data.getUint32) { + ret = this.data.getUint32(offset, false); + } else { + ret = this.data.readUInt32BE(offset); + } + if (p === undefined) this.offset += 4; + + return ret; + } + + readSInt32LE(p) { + var offset = (typeof p) == 'number' ? p : this.offset; + var ret; + if (this.data.getInt32) { + ret = this.data.getInt32(offset, true); + } else { + ret = this.data.readInt32LE(offset); + } + if (p === undefined) this.offset += 4; + + return ret; + } + + readSInt32BE(p) { + var offset = (typeof p) == 'number' ? p : this.offset; + var ret; + if (this.data.getInt32) { + ret = this.data.getInt32(offset, false); + } else { + ret = this.data.readInt32BE(offset); + } + if (p === undefined) this.offset += 4; + + return ret; + } + + readFloat32LE(p) { + var offset = (typeof p) == 'number' ? p : this.offset; + var ret; + if (this.data.getFloat32) { + ret = this.data.getFloat32(offset, true); + } else { + ret = this.data.readFloatLE(offset); + } + if (p === undefined) this.offset += 4; + + return ret; + } + + readFloat32BE(p) { + var offset = (typeof p) == 'number' ? p : this.offset; + var ret; + if (this.data.getFloat32) { + ret = this.data.getFloat32(offset, false); + } else { + ret = this.data.readFloatBE(offset); + } + if (p === undefined) this.offset += 4; + + return ret; + } + + readFloat64LE(p) { + var offset = (typeof p) == 'number' ? p : this.offset; + var ret; + if (this.data.getFloat64) { + ret = this.data.getFloat64(offset, true); + } else { + ret = this.data.readDoubleLE(offset); + } + if (p === undefined) this.offset += 8; + + return ret; + } + + readFloat64BE(p) { + var offset = (typeof p) == 'number' ? p : this.offset; + var ret; + if (this.data.getFloat64) { + ret = this.data.getFloat64(offset, false); + } else { + ret = this.data.readDoubleBE(offset); + } + if (p === undefined) this.offset += 8; + + return ret; + } + + toString() { + var out = ''; + for (var i = 0; i < this.length; i++) { + if (out) out += ' '; + var char = this.readUInt8(i).toString(16); + if (char.length == 1) out += '0'; + out += char; + } + + return out; + } +} diff --git a/client/js/agario-client/client.js b/client/js/agario-client/client.js new file mode 100644 index 0000000..d29f421 --- /dev/null +++ b/client/js/agario-client/client.js @@ -0,0 +1,670 @@ +'use strict'; + +import EventEmitter from 'events'; + +import Packet from './Packet'; +import servers from './servers'; +import Account from './Account'; +import Ball from './Ball'; + +function Client(client_name) { + //you can change this values + this.client_name = client_name; //name used for log + this.debug = 1; //debug level, 0-5 (5 will output extremely lot of data) + this.inactive_destroy = 5 * 60 * 1000; //time in ms when to destroy inactive balls + this.inactive_check = 10 * 1000; //time in ms when to search inactive balls + this.spawn_interval = 200; //time in ms for respawn interval. 0 to disable (if your custom server don't have spawn problems) + this.spawn_attempts = 25; //how much attempts to spawn before give up (official servers do have unstable spawn problems) + this.agent = null; //agent for connection. Check additional info in readme + this.local_address = null; //local interface to bind to for network connections (IP address of interface) + this.headers = { //headers for WebSocket connection. + Origin: 'http://agar.io', + }; + + //don't change things below if you don't understand what you're doing + + this.tick_counter = 0; //number of ticks (packet ID 16 counter) + this.inactive_interval = 0; //ID of setInterval() + this.balls = {}; //all balls + this.my_balls = []; //IDs of my balls + this.score = 0; //my score + this.leaders = []; //IDs of leaders in FFA mode + this.teams_scores = []; //scores of teams in Teams mode + this.auth_token = ''; //auth token. Check README.md how to get it + this.auth_provider = 1; //auth provider. 1 = facebook, 2 = google + this.spawn_attempt = 0; //attempt to spawn + this.spawn_interval_id = 0; //ID of setInterval() +} + +Client.prototype = { + connect: function (server, key) { + var opt = { + headers: this.headers, + }; + if (this.agent) opt.agent = this.agent; + if (this.local_address) opt.localAddress = this.local_address; + + this.ws = new WebSocket(server, null, opt); + this.ws.binaryType = 'arraybuffer'; + this.ws.onopen = this.onConnect.bind(this); + this.ws.onmessage = this.onMessage.bind(this); + this.ws.onclose = this.onDisconnect.bind(this); + this.ws.onerror = this.onError.bind(this); + this.server = server; + this.key = key; + + if (this.debug >= 1) { + if (!key) this.log('[warning] You did not specified "key" for Client.connect(server, key)\n' + + ' If server will not accept you, this may be the problem'); + this.log('connecting...'); + } + + this.emitEvent('connecting'); + }, + + disconnect: function () { + if (this.debug >= 1) + this.log('disconnect() called'); + + if (!this.ws) { + if (this.debug >= 1) + this.log('[warning] disconnect() called before connect(), ignoring this call'); + return false; + } + + this.ws.close(); + return true; + }, + + onConnect: function () { + var client = this; + + if (this.debug >= 1) + this.log('connected to server'); + + this.inactive_interval = setInterval(this.detsroyInactive.bind(this), this.inactive_check); + + var buf = new Buffer(5); + buf.writeUInt8(254, 0); + buf.writeUInt32LE(5, 1); + + if (this.ws.readyState !== WebSocket.OPEN) { //`ws` bug https://github.com/websockets/ws/issues/669 `Crash 2` + this.onPacketError(new Packet(buf), new Error('ws bug #669:crash2 detected, `onopen` called with not established connection')); + return; + } + + this.send(buf); + + buf = new Buffer(5); + buf.writeUInt8(255, 0); + buf.writeUInt32LE(2200049715, 1); + this.send(buf); + + var i; + + if (this.key) { + buf = new Buffer(1 + this.key.length); + buf.writeUInt8(80, 0); + for (i = 1; i <= this.key.length; ++i) { + buf.writeUInt8(this.key.charCodeAt(i - 1), i); + } + this.send(buf); + } + if (this.auth_token) { + buf = new Buffer(2 + this.auth_token.length); + buf.writeUInt8(82, 0); + buf.writeUInt8(this.auth_provider, 1); + for (i = 1; i <= this.auth_token.length; ++i) { + buf.writeUInt8(this.auth_token.charCodeAt(i - 1), i + 1); + } + this.send(buf); + } + + client.emitEvent('connected'); + }, + + onError: function (e) { + if (this.debug >= 1) + this.log('connection error: ' + e); + + this.emitEvent('connectionError', e); + this.reset(); + }, + + onDisconnect: function () { + if (this.debug >= 1) + this.log('disconnected'); + + this.emitEvent('disconnect'); + this.reset(); + }, + + onMessage: function (e) { + var packet = new Packet(e); + if (!packet.length) { + return this.onPacketError(packet, new Error('Empty packet received')); + } + var packet_id = packet.readUInt8(); + var processor = this.processors[packet_id]; + if (!processor) return this.log('[warning] unknown packet ID(' + packet_id + '): ' + packet.toString()); + + if (this.debug >= 4) + this.log('RECV packet ID=' + packet_id + ' LEN=' + packet.length); + if (this.debug >= 5) + this.log('dump: ' + packet.toString()); + + this.emitEvent('message', packet); + + try { + processor(this, packet); + }catch (err) { + this.onPacketError(packet, err); + } + }, + + // Had to do this because sometimes somehow packets get moving by 1 byte + // https://github.com/pulviscriptor/agario-client/issues/46#issuecomment-169764771 + onPacketError: function (packet, err) { + var crash = true; + + this.emitEvent('packetError', packet, err, function () { + crash = false; + }); + + if (crash) { + if (this.debug >= 1) + this.log('Packet error detected! Check packetError event in README.md'); + throw err; + } + }, + + send: function (buf) { + if (this.debug >= 4) + this.log('SEND packet ID=' + buf.readUInt8(0) + ' LEN=' + buf.length); + + if (this.debug >= 5) + this.log('dump: ' + (new Packet(buf).toString())); + + this.ws.send(buf); + }, + + reset: function () { + if (this.debug >= 3) + this.log('reset()'); + + clearInterval(this.inactive_interval); + clearInterval(this.spawn_interval_id); + this.spawn_interval_id = 0; + this.leaders = []; + this.teams_scores = []; + this.my_balls = []; + this.spawn_attempt = 0; + + for (var k in this.balls) if (this.balls.hasOwnProperty(k)) this.balls[k].destroy({ reason:'reset' }); + this.emitEvent('reset'); + }, + + detsroyInactive: function () { + var time = Date.now(); + + if (this.debug >= 3) + this.log('destroying inactive balls'); + + for (var k in this.balls) { + if (!this.balls.hasOwnProperty(k)) continue; + var ball = this.balls[k]; + if (time - ball.last_update < this.inactive_destroy) continue; + if (ball.visible) continue; + + if (this.debug >= 3) + this.log('destroying inactive ' + ball); + + ball.destroy({ reason: 'inactive' }); + } + }, + + processors: { + //tick + 16: function (client, packet) { + var eaters_count = packet.readUInt16LE(); + var ball_id; + var ball; + + client.tick_counter++; + + //reading eat events + for (var i = 0; i < eaters_count; i++) { + var eater_id = packet.readUInt32LE(); + var eaten_id = packet.readUInt32LE(); + + if (client.debug >= 4) + client.log(eater_id + ' ate ' + eaten_id + ' (' + client.balls[eater_id] + '>' + client.balls[eaten_id] + ')'); + + if (!client.balls[eater_id]) new Ball(client, eater_id); + client.balls[eater_id].update(); + if (client.balls[eaten_id]) client.balls[eaten_id].destroy({ reason:'eaten', by:eater_id }); + + client.emitEvent('somebodyAteSomething', eater_id, eaten_id); + } + + //reading actions of balls + while (1) { + var is_virus = false; + var coordinate_x; + var coordinate_y; + var size; + var color; + var nick = null; + + ball_id = packet.readUInt32LE(); + if (ball_id === 0) break; + coordinate_x = packet.readSInt32LE(); + coordinate_y = packet.readSInt32LE(); + size = packet.readSInt16LE(); + + var color_R = packet.readUInt8(); + var color_G = packet.readUInt8(); + var color_B = packet.readUInt8(); + + color = (color_R << 16 | color_G << 8 | color_B).toString(16); + color = '#' + ('000000' + color).substr(-6); + + var opt = packet.readUInt8(); + is_virus = !!(opt & 1); + var something_1 = !!(opt & 16); //todo what is this? + + //reserved for future use? + if (opt & 2) { + packet.offset += packet.readUInt32LE(); + } + var char; + if (opt & 4) { + var something_2 = ''; //todo something related to premium skins + while (1) { + char = packet.readUInt8(); + if (char === 0) break; + if (!something_2) something_2 = ''; + something_2 += String.fromCharCode(char); + } + } + + while (1) { + char = packet.readUInt16LE(); + if (char === 0) break; + if (!nick) nick = ''; + nick += String.fromCharCode(char); + } + + ball = client.balls[ball_id] || new Ball(client, ball_id); + ball.color = color; + ball.virus = is_virus; + ball.setCords(coordinate_x, coordinate_y); + ball.setSize(size); + if (nick) ball.setName(nick); + ball.update_tick = client.tick_counter; + ball.appear(); + ball.update(); + + if (client.debug >= 5) + client.log('action: ball_id=' + ball_id + ' coordinate_x=' + coordinate_x + ' coordinate_y=' + coordinate_y + ' size=' + size + ' is_virus=' + is_virus + ' nick=' + nick); + + client.emitEvent('ballAction', ball_id, coordinate_x, coordinate_y, size, is_virus, nick); + } + + var balls_on_screen_count = packet.readUInt32LE(); + + //disappear events + for (i = 0; i < balls_on_screen_count; i++) { + ball_id = packet.readUInt32LE(); + + ball = client.balls[ball_id] || new Ball(client, ball_id); + ball.update_tick = client.tick_counter; + ball.update(); + if (ball.mine) { + ball.destroy({ reason: 'merge' }); + client.emitEvent('merge', ball.id); + }else { + ball.disappear(); + } + } + }, + + //update spectating coordinates in "spectate" mode + 17: function (client, packet) { + var x = packet.readFloat32LE(); + var y = packet.readFloat32LE(); + var zoom = packet.readFloat32LE(); + + if (client.debug >= 4) + client.log('spectate FOV update: x=' + x + ' y=' + y + ' zoom=' + zoom); + + client.emitEvent('spectateFieldUpdate', x, y, zoom); + }, + + 18: function () { + for (var k in this.balls) if (this.balls.hasOwnProperty(k)) this.balls[k].destroy({ reason:'server-forced' }); + }, + + 20: function () { + //i dont know what this is + //in original code it clears our balls array, but i never saw this packet + }, + + //debug line drawn from the player to the specified point + 21: function (client, packet) { + var line_x = packet.readSInt16LE(); + var line_y = packet.readSInt16LE(); + + if (client.debug >= 4) + client.log('debug line drawn from x=' + line_x + ' y=' + line_y); + client.emitEvent('debugLine', line_x, line_y); + }, + + //new ID of your ball (when you join or press space) + 32: function (client, packet) { + var ball_id = packet.readUInt32LE(); + var ball = client.balls[ball_id] || new Ball(client, ball_id); + ball.mine = true; + if (!client.my_balls.length) client.score = 0; + client.my_balls.push(ball_id); + + if (client.debug >= 2) + client.log('my new ball: ' + ball_id); + + if (client.spawn_interval_id) { + if (client.debug >= 4) + client.log('detected new ball, disabling spawn() interval'); + client.spawn_attempt = 0; + clearInterval(client.spawn_interval_id); + client.spawn_interval_id = 0; + } + + client.emitEvent('myNewBall', ball_id); + }, + + //leaderboard update in FFA mode + 49: function (client, packet) { + var users = []; + var count = packet.readUInt32LE(); + + for (var i = 0; i < count; i++) { + var id = packet.readUInt32LE(); + + var name = ''; + while (1) { + var char = packet.readUInt16LE(); + if (char === 0) break; + name += String.fromCharCode(char); + } + + users.push(id); + var ball = client.balls[id] || new Ball(client, id); + if (name) ball.setName(name); + ball.update(); + } + + if (JSON.stringify(client.leaders) == JSON.stringify(users)) return; + var old_leaders = client.leaders; + client.leaders = users; + + if (client.debug >= 3) + client.log('leaders update: ' + JSON.stringify(users)); + + client.emitEvent('leaderBoardUpdate', old_leaders, users); + }, + + //teams scored update in teams mode + 50: function (client, packet) { + var teams_count = packet.readUInt32LE(); + var teams_scores = []; + + for (var i = 0; i < teams_count; ++i) { + teams_scores.push(packet.readFloat32LE()); + } + + if (JSON.stringify(client.teams_scores) == JSON.stringify(teams_scores)) return; + var old_scores = client.teams_scores; + + if (client.debug >= 3) + client.log('teams scores update: ' + JSON.stringify(teams_scores)); + + client.teams_scores = teams_scores; + + client.emitEvent('teamsScoresUpdate', old_scores, teams_scores); + }, + + //map size load + 64: function (client, packet) { + var min_x = packet.readFloat64LE(); + var min_y = packet.readFloat64LE(); + var max_x = packet.readFloat64LE(); + var max_y = packet.readFloat64LE(); + + if (client.debug >= 2) + client.log('map size: ' + [min_x, min_y, max_x, max_y].join(',')); + + client.emitEvent('mapSizeLoad', min_x, min_y, max_x, max_y); + }, + + //another unknown backet + 72: function () { + //packet is sent by server but not used in original code + }, + + 81: function (client, packet) { + var level = packet.readUInt32LE(); + var curernt_exp = packet.readUInt32LE(); + var need_exp = packet.readUInt32LE(); + + if (client.debug >= 2) + client.log('experience update: ' + [level, curernt_exp, need_exp].join(',')); + + client.emitEvent('experienceUpdate', level, curernt_exp, need_exp); + }, + + 102: function () { + // This packet used for some shop server wss://web-live-v3-0.agario.miniclippt.com/ws + // There is some "reserved" code for it in "account.js" you can check that. But it is not used since this server is useless for client + // If you need that server support, you may create issue https://github.com/pulviscriptor/agario-client/issues + }, + + 103: function () { + // Processor for that packet is missing in official client but @SzAmmi reporting that he receives it + // https://github.com/pulviscriptor/agario-client/issues/94 + }, + + 240: function (client, packet) { + packet.offset += 4; + var packet_id = packet.readUInt8(); + var processor = client.processors[packet_id]; + if (!processor) return client.log('[warning] unknown packet ID(240->' + packet_id + '): ' + packet.toString()); + processor(client, packet); + }, + + //somebody won, end of the game (server restart) + 254: function (client) { + if (client.debug >= 1) + client.log(client.balls[client.leaders[0]] + ' WON THE GAME! Server going for restart'); + + client.emitEvent('winner', client.leaders[0]); + }, + }, + + updateScore: function () { + var potential_score = 0; + for (var i = 0; i < this.my_balls.length; i++) { + var ball_id = this.my_balls[i]; + var ball = this.balls[ball_id]; + potential_score += Math.pow(ball.size, 2); + } + var old_score = this.score; + var new_score = Math.max(this.score, Math.floor(potential_score / 100)); + + if (this.score == new_score) return; + this.score = new_score; + this.emitEvent('scoreUpdate', old_score, new_score); + + if (this.debug >= 2) + this.log('score: ' + new_score); + + }, + + log: function (msg) { + console.log(this.client_name + ': ' + msg); + }, + + // Fix https://github.com/pulviscriptor/agario-client/issues/95 + emitEvent: function () { + var args = []; + for (var i = 0; i < arguments.length; i++) args.push(arguments[i]); + try { + this.emit.apply(this, args); + } catch (e) { + process.nextTick(function () { + throw e; + }); + } + }, + + //functions that you can call to control your balls + + //spawn ball + spawn: function (name) { + if (this.debug >= 3) + this.log('spawn() called, name=' + name); + + if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { + if (this.debug >= 1) + this.log('[warning] spawn() was called when connection was not established, packet will be dropped'); + return false; + } + + var buf = new Buffer(1 + 2 * name.length); + buf.writeUInt8(0, 0); + for (var i = 0; i < name.length; i++) { + buf.writeUInt16LE(name.charCodeAt(i), 1 + i * 2); + } + this.send(buf); + + //fix for unstable spawn on official servers + if (!this.spawn_attempt && this.spawn_interval) { + if (this.debug >= 4) + this.log('Starting spawn() interval'); + + var that = this; + this.spawn_attempt = 1; + this.spawn_interval_id = setInterval(function () { + if (that.debug >= 4) + that.log('spawn() interval tick, attempt ' + that.spawn_attempt + '/' + that.spawn_attempts); + + if (that.spawn_attempt >= that.spawn_attempts) { + if (that.debug >= 1) + that.log('[warning] spawn() interval gave up! Disconnecting from server!'); + that.spawn_attempt = 0; + clearInterval(that.spawn_interval_id); + that.spawn_interval_id = 0; + that.disconnect(); + return; + } + that.spawn_attempt++; + that.spawn(name); + }, that.spawn_interval); + } + + return true; + }, + + //activate spectate mode + spectate: function () { + if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { + if (this.debug >= 1) + this.log('[warning] spectate() was called when connection was not established, packet will be dropped'); + return false; + } + + var buf = new Buffer([1]); + this.send(buf); + + return true; + }, + + //switch spectate mode (toggle between free look view and leader view) + spectateModeToggle: function () { + if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { + if (this.debug >= 1) + this.log('[warning] spectateModeToggle() was called when connection was not established, packet will be dropped'); + return false; + } + + var buf = new Buffer([18]); + this.send(buf); + buf = new Buffer([19]); + this.send(buf); + + return true; + }, + + moveTo: function (x, y) { + if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { + if (this.debug >= 1) + this.log('[warning] moveTo() was called when connection was not established, packet will be dropped'); + return false; + } + var buf = new Buffer(13); + buf.writeUInt8(16, 0); + buf.writeInt32LE(Math.round(x), 1); + buf.writeInt32LE(Math.round(y), 5); + buf.writeUInt32LE(0, 9); + this.send(buf); + + return true; + }, + + //split your balls + //they will split in direction that you have set with moveTo() + split: function () { + if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { + if (this.debug >= 1) + this.log('[warning] split() was called when connection was not established, packet will be dropped'); + return false; + } + var buf = new Buffer([17]); + this.send(buf); + + return true; + }, + + //eject some mass + //mass will eject in direction that you have set with moveTo() + eject: function () { + if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { + if (this.debug >= 1) + this.log('[warning] eject() was called when connection was not established, packet will be dropped'); + return false; + } + var buf = new Buffer([21]); + this.send(buf); + + return true; + }, + + //deprecated + /* jshint ignore:start */ + set facebook_key(_) { + console.trace('Property "facebook_key" is deprecated. Please check in README.md how new authorization works'); + }, + /* jshint ignore:end */ +}; + +// Inherit from EventEmitter +for (var key in EventEmitter.prototype) { + if (!EventEmitter.prototype.hasOwnProperty(key)) continue; + Client.prototype[key] = Ball.prototype[key] = EventEmitter.prototype[key]; +} + +Client.servers = servers; +Client.Packet = Packet; +Client.Account = Account; +Client.Ball = Ball; + +export default Client; diff --git a/client/js/agario-client/servers.js b/client/js/agario-client/servers.js new file mode 100644 index 0000000..286aa4e --- /dev/null +++ b/client/js/agario-client/servers.js @@ -0,0 +1,157 @@ +'use strict'; + +import * as http from 'http'; + +var servers = { + init_key: 2200049715, //used in initial packet id 255 and POST requests, hardcoded in client + + resolveDomainName: function(domain, post_opt, cb) { + return cb({ + error: 'LOOKUP_FAIL', + error_source: 'not support' + }); + }, + + postRequest: function(opt, cb) { + var ret = { + error: null, + error_source: null, + res: null, + data: null, + server: null, + key: null, + }; + + var options = { + host: opt.ip || 'm.agar.io', + port: 80, + path: opt.url || '/', + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': opt.data.length, + Origin: 'http://agar.io', + Referer: 'http://agar.io/', + Host: 'm.agar.io', + }, + }; + if (opt.agent) options.agent = opt.agent; + if (opt.local_address) options.localAddress = opt.local_address; + + var req = http.request(options, function(res) { + var server = ''; + + res.setEncoding('utf8'); + res.on('data', function(chunk) { + server += chunk; + }); + res.on('end', function() { + var data = server.split('\n'); + + if (res.statusCode != 200) { + ret.error = 'WRONG_HTTP_CODE'; + ret.res = res; + ret.data = server; + } else if (!data[opt.res_data_index === undefined ? 1 : opt.res_data_index]) { + ret.error = 'WRONG_DATA_FORMAT'; + ret.res = res; + ret.data = server; + } else { + ret.res = res; + ret.data = server; + ret.server = data[0]; + ret.key = data[1]; + } + + cb(ret); + }); + }); + + req.on('error', function(e) { + ret.error = 'REQUEST_ERROR'; + ret.error_source = e; + return cb(ret); + }); + + req.write(opt.data); + req.end(); + }, + + getFFAServer: function(opt, cb) { + if (!opt) opt = {}; + var region = opt.region || 'EU-London'; + var post_opt = { + data: region + '\n' + servers.init_key, + agent: opt.agent, + ip: opt.ip, + resolve: opt.resolve, + }; + + servers.postRequest(post_opt, cb); + }, + + getTeamsServer: function(opt, cb) { + if (!opt) opt = {}; + var region = opt.region || 'EU-London'; + var post_opt = { + data: region + ':teams\n' + servers.init_key, + agent: opt.agent, + ip: opt.ip, + resolve: opt.resolve, + }; + servers.postRequest(post_opt, cb); + }, + + getExperimentalServer: function(opt, cb) { + if (!opt) opt = {}; + var region = opt.region || 'EU-London'; + var post_opt = { + data: region + ':experimental\n' + servers.init_key, + agent: opt.agent, + ip: opt.ip, + resolve: opt.resolve, + }; + if (!opt.ip && opt.resolve) { + servers.resolveDomainName('m.agar.io', post_opt, cb); + } else { + servers.postRequest(post_opt, cb); + } + }, + + createParty: function(opt, cb) { + if (!opt) opt = {}; + var region = opt.region || 'EU-London'; + var post_opt = { + data: region + ':party\n' + servers.init_key, + agent: opt.agent, + ip: opt.ip, + resolve: opt.resolve, + }; + if (!opt.ip && opt.resolve) { + servers.resolveDomainName('m.agar.io', post_opt, cb); + } else { + servers.postRequest(post_opt, cb); + } + }, + + getPartyServer: function(opt, cb) { + if (!opt.party_key) throw new Error('getPartyServer wants opt.party_key'); + var party_key = (opt.party_key.indexOf('#') >= 0) ? + opt.party_key.substr(opt.party_key.indexOf('#') + 1) : opt.party_key; + var post_opt = { + url: '/getToken', + data: party_key, + res_data_index: 0, + agent: opt.agent, + ip: opt.ip, + resolve: opt.resolve, + }; + servers.postRequest(post_opt, function(res) { + if (!res.server) return cb(res); + res.key = party_key; + cb(res); + }); + }, +}; + +export default servers; diff --git a/client/js/controller.js b/client/js/controller.js index 2b856fd..f9a10c6 100644 --- a/client/js/controller.js +++ b/client/js/controller.js @@ -1,10 +1,11 @@ 'use strict'; -const Dat = require('dat-gui'); -const Connector = require('./connector'); -const constants = require('./constants'); +import Dat from 'dat-gui'; +import Connector from './connector'; +import constants from './constants'; +import AgarioClient from './agario-client/client'; -class Controller { +export default class Controller { constructor(client) { this.client = client; this.connector = new Connector(); @@ -124,5 +125,3 @@ class Controller { } } } - -module.exports = Controller; diff --git a/client/js/main.js b/client/js/main.js index f02eaeb..ba89767 100644 --- a/client/js/main.js +++ b/client/js/main.js @@ -2,12 +2,12 @@ /* global performance: false */ -var PIXI = require('pixi.js'); +import PIXI from 'pixi.js'; -var Client = require('heroandtn3/agario-client'); -var Controller = require('./controller'); -var Viewer = require('./viewer'); -var Pointer = require('./pointer'); +import Client from './agario-client/client'; +import Controller from './controller'; +import Viewer from './viewer'; +import Pointer from './pointer'; PIXI.Container.prototype.bringToFront = function () { if (this.parent) { diff --git a/config.js b/config.js index b5f2bcd..4d8384b 100644 --- a/config.js +++ b/config.js @@ -19,28 +19,16 @@ System.config({ "core-js": "npm:core-js@1.2.6", "dat-gui": "npm:dat-gui@0.5.0", "events": "npm:events@1.1.0", - "heroandtn3/agario-client": "github:heroandtn3/agario-client@workaround", + "http": "github:jspm/nodelibs-http@1.7.1", + "https": "github:jspm/nodelibs-https@0.1.0", "pixi.js": "npm:pixi.js@3.0.9", "stats.js": "npm:stats.js@0.0.14-master", - "github:heroandtn3/agario-client@workaround": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "events": "github:jspm/nodelibs-events@0.1.1", - "http": "github:jspm/nodelibs-http@1.7.1", - "process": "github:jspm/nodelibs-process@0.1.2", - "ws": "npm:ws@0.7.2" - }, "github:jspm/nodelibs-assert@0.1.0": { "assert": "npm:assert@1.3.0" }, "github:jspm/nodelibs-buffer@0.1.0": { "buffer": "npm:buffer@3.6.0" }, - "github:jspm/nodelibs-constants@0.1.0": { - "constants-browserify": "npm:constants-browserify@0.0.1" - }, - "github:jspm/nodelibs-crypto@0.1.0": { - "crypto-browserify": "npm:crypto-browserify@3.11.0" - }, "github:jspm/nodelibs-events@0.1.1": { "events": "npm:events@1.0.2" }, @@ -70,21 +58,12 @@ System.config({ "github:jspm/nodelibs-stream@0.1.0": { "stream-browserify": "npm:stream-browserify@1.0.0" }, - "github:jspm/nodelibs-string_decoder@0.1.0": { - "string_decoder": "npm:string_decoder@0.10.31" - }, "github:jspm/nodelibs-url@0.1.0": { "url": "npm:url@0.10.3" }, "github:jspm/nodelibs-util@0.1.0": { "util": "npm:util@0.10.3" }, - "github:jspm/nodelibs-vm@0.1.0": { - "vm-browserify": "npm:vm-browserify@0.0.4" - }, - "github:jspm/nodelibs-zlib@0.1.0": { - "browserify-zlib": "npm:browserify-zlib@0.1.4" - }, "npm:acorn@1.2.2": { "fs": "github:jspm/nodelibs-fs@0.1.2", "path": "github:jspm/nodelibs-path@0.1.0", @@ -97,14 +76,6 @@ System.config({ "path": "github:jspm/nodelibs-path@0.1.0", "process": "github:jspm/nodelibs-process@0.1.2" }, - "npm:asn1.js@4.3.0": { - "assert": "github:jspm/nodelibs-assert@0.1.0", - "bn.js": "npm:bn.js@4.10.0", - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "inherits": "npm:inherits@2.0.1", - "minimalistic-assert": "npm:minimalistic-assert@1.0.0", - "vm": "github:jspm/nodelibs-vm@0.1.0" - }, "npm:assert@1.3.0": { "util": "npm:util@0.10.3" }, @@ -118,14 +89,6 @@ System.config({ "npm:babel-runtime@5.8.35": { "process": "github:jspm/nodelibs-process@0.1.2" }, - "npm:bindings@1.2.1": { - "fs": "github:jspm/nodelibs-fs@0.1.2", - "path": "github:jspm/nodelibs-path@0.1.0", - "process": "github:jspm/nodelibs-process@0.1.2" - }, - "npm:bn.js@4.10.0": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0" - }, "npm:brfs@1.4.3": { "buffer": "github:jspm/nodelibs-buffer@0.1.0", "fs": "github:jspm/nodelibs-fs@0.1.2", @@ -137,65 +100,9 @@ System.config({ "systemjs-json": "github:systemjs/plugin-json@0.1.0", "through2": "npm:through2@2.0.0" }, - "npm:browserify-aes@1.0.6": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "buffer-xor": "npm:buffer-xor@1.0.3", - "cipher-base": "npm:cipher-base@1.0.2", - "create-hash": "npm:create-hash@1.1.2", - "crypto": "github:jspm/nodelibs-crypto@0.1.0", - "evp_bytestokey": "npm:evp_bytestokey@1.0.0", - "fs": "github:jspm/nodelibs-fs@0.1.2", - "inherits": "npm:inherits@2.0.1", - "systemjs-json": "github:systemjs/plugin-json@0.1.0" - }, - "npm:browserify-cipher@1.0.0": { - "browserify-aes": "npm:browserify-aes@1.0.6", - "browserify-des": "npm:browserify-des@1.0.0", - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "crypto": "github:jspm/nodelibs-crypto@0.1.0", - "evp_bytestokey": "npm:evp_bytestokey@1.0.0" - }, - "npm:browserify-des@1.0.0": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "cipher-base": "npm:cipher-base@1.0.2", - "crypto": "github:jspm/nodelibs-crypto@0.1.0", - "des.js": "npm:des.js@1.0.0", - "inherits": "npm:inherits@2.0.1" - }, - "npm:browserify-rsa@4.0.0": { - "bn.js": "npm:bn.js@4.10.0", - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "constants": "github:jspm/nodelibs-constants@0.1.0", - "crypto": "github:jspm/nodelibs-crypto@0.1.0", - "randombytes": "npm:randombytes@2.0.2" - }, - "npm:browserify-sign@4.0.0": { - "bn.js": "npm:bn.js@4.10.0", - "browserify-rsa": "npm:browserify-rsa@4.0.0", - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "create-hash": "npm:create-hash@1.1.2", - "create-hmac": "npm:create-hmac@1.1.4", - "crypto": "github:jspm/nodelibs-crypto@0.1.0", - "elliptic": "npm:elliptic@6.2.3", - "inherits": "npm:inherits@2.0.1", - "parse-asn1": "npm:parse-asn1@5.0.0", - "stream": "github:jspm/nodelibs-stream@0.1.0" - }, - "npm:browserify-zlib@0.1.4": { - "assert": "github:jspm/nodelibs-assert@0.1.0", - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "pako": "npm:pako@0.2.8", - "process": "github:jspm/nodelibs-process@0.1.2", - "readable-stream": "npm:readable-stream@2.0.5", - "util": "github:jspm/nodelibs-util@0.1.0" - }, "npm:buffer-equal@0.0.1": { "buffer": "github:jspm/nodelibs-buffer@0.1.0" }, - "npm:buffer-xor@1.0.3": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "systemjs-json": "github:systemjs/plugin-json@0.1.0" - }, "npm:buffer@3.6.0": { "base64-js": "npm:base64-js@0.0.8", "child_process": "github:jspm/nodelibs-child_process@0.1.0", @@ -204,25 +111,12 @@ System.config({ "isarray": "npm:isarray@1.0.0", "process": "github:jspm/nodelibs-process@0.1.2" }, - "npm:bufferutil@1.1.0": { - "bindings": "npm:bindings@1.2.1", - "nan": "npm:nan@1.8.4" - }, - "npm:cipher-base@1.0.2": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "inherits": "npm:inherits@2.0.1", - "stream": "github:jspm/nodelibs-stream@0.1.0", - "string_decoder": "github:jspm/nodelibs-string_decoder@0.1.0" - }, "npm:concat-stream@1.4.10": { "buffer": "github:jspm/nodelibs-buffer@0.1.0", "inherits": "npm:inherits@2.0.1", "readable-stream": "npm:readable-stream@1.1.13", "typedarray": "npm:typedarray@0.0.6" }, - "npm:constants-browserify@0.0.1": { - "systemjs-json": "github:systemjs/plugin-json@0.1.0" - }, "npm:core-js@1.2.6": { "fs": "github:jspm/nodelibs-fs@0.1.2", "path": "github:jspm/nodelibs-path@0.1.0", @@ -232,66 +126,13 @@ System.config({ "npm:core-util-is@1.0.2": { "buffer": "github:jspm/nodelibs-buffer@0.1.0" }, - "npm:create-ecdh@4.0.0": { - "bn.js": "npm:bn.js@4.10.0", - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "crypto": "github:jspm/nodelibs-crypto@0.1.0", - "elliptic": "npm:elliptic@6.2.3" - }, - "npm:create-hash@1.1.2": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "cipher-base": "npm:cipher-base@1.0.2", - "crypto": "github:jspm/nodelibs-crypto@0.1.0", - "fs": "github:jspm/nodelibs-fs@0.1.2", - "inherits": "npm:inherits@2.0.1", - "ripemd160": "npm:ripemd160@1.0.1", - "sha.js": "npm:sha.js@2.4.4" - }, - "npm:create-hmac@1.1.4": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "create-hash": "npm:create-hash@1.1.2", - "crypto": "github:jspm/nodelibs-crypto@0.1.0", - "inherits": "npm:inherits@2.0.1", - "stream": "github:jspm/nodelibs-stream@0.1.0" - }, - "npm:crypto-browserify@3.11.0": { - "browserify-cipher": "npm:browserify-cipher@1.0.0", - "browserify-sign": "npm:browserify-sign@4.0.0", - "create-ecdh": "npm:create-ecdh@4.0.0", - "create-hash": "npm:create-hash@1.1.2", - "create-hmac": "npm:create-hmac@1.1.4", - "diffie-hellman": "npm:diffie-hellman@5.0.2", - "inherits": "npm:inherits@2.0.1", - "pbkdf2": "npm:pbkdf2@3.0.4", - "public-encrypt": "npm:public-encrypt@4.0.0", - "randombytes": "npm:randombytes@2.0.2" - }, - "npm:des.js@1.0.0": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "inherits": "npm:inherits@2.0.1", - "minimalistic-assert": "npm:minimalistic-assert@1.0.0" - }, - "npm:diffie-hellman@5.0.2": { - "bn.js": "npm:bn.js@4.10.0", - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "crypto": "github:jspm/nodelibs-crypto@0.1.0", - "miller-rabin": "npm:miller-rabin@4.0.0", - "randombytes": "npm:randombytes@2.0.2", - "systemjs-json": "github:systemjs/plugin-json@0.1.0" - }, "npm:duplexer2@0.0.2": { - "readable-stream": "npm:readable-stream@1.1.13" + "readable-stream": "npm:readable-stream@1.1.13", + "systemjs-json": "github:systemjs/plugin-json@0.1.0" }, "npm:earcut@2.0.8": { "process": "github:jspm/nodelibs-process@0.1.2" }, - "npm:elliptic@6.2.3": { - "bn.js": "npm:bn.js@4.10.0", - "brorand": "npm:brorand@1.0.5", - "hash.js": "npm:hash.js@1.0.3", - "inherits": "npm:inherits@2.0.1", - "systemjs-json": "github:systemjs/plugin-json@0.1.0" - }, "npm:escodegen@0.0.28": { "esprima": "npm:esprima@1.0.4", "estraverse": "npm:estraverse@1.3.2", @@ -319,11 +160,6 @@ System.config({ "fs": "github:jspm/nodelibs-fs@0.1.2", "process": "github:jspm/nodelibs-process@0.1.2" }, - "npm:evp_bytestokey@1.0.0": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "create-hash": "npm:create-hash@1.1.2", - "crypto": "github:jspm/nodelibs-crypto@0.1.0" - }, "npm:falafel@1.2.0": { "acorn": "npm:acorn@1.2.2", "buffer": "github:jspm/nodelibs-buffer@0.1.0", @@ -334,50 +170,21 @@ System.config({ "npm:has@1.0.1": { "function-bind": "npm:function-bind@1.0.2" }, - "npm:hash.js@1.0.3": { - "inherits": "npm:inherits@2.0.1" - }, "npm:https-browserify@0.0.0": { "http": "github:jspm/nodelibs-http@1.7.1" }, "npm:inherits@2.0.1": { "util": "github:jspm/nodelibs-util@0.1.0" }, - "npm:miller-rabin@4.0.0": { - "bn.js": "npm:bn.js@4.10.0", - "brorand": "npm:brorand@1.0.5" - }, - "npm:nan@1.8.4": { - "path": "github:jspm/nodelibs-path@0.1.0" - }, - "npm:options@0.0.6": { - "fs": "github:jspm/nodelibs-fs@0.1.2" - }, - "npm:pako@0.2.8": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "process": "github:jspm/nodelibs-process@0.1.2" + "npm:isarray@1.0.0": { + "systemjs-json": "github:systemjs/plugin-json@0.1.0" }, - "npm:parse-asn1@5.0.0": { - "asn1.js": "npm:asn1.js@4.3.0", - "browserify-aes": "npm:browserify-aes@1.0.6", - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "create-hash": "npm:create-hash@1.1.2", - "evp_bytestokey": "npm:evp_bytestokey@1.0.0", - "pbkdf2": "npm:pbkdf2@3.0.4", + "npm:object-inspect@0.4.0": { "systemjs-json": "github:systemjs/plugin-json@0.1.0" }, "npm:path-browserify@0.0.0": { "process": "github:jspm/nodelibs-process@0.1.2" }, - "npm:pbkdf2@3.0.4": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "child_process": "github:jspm/nodelibs-child_process@0.1.0", - "create-hmac": "npm:create-hmac@1.1.4", - "crypto": "github:jspm/nodelibs-crypto@0.1.0", - "path": "github:jspm/nodelibs-path@0.1.0", - "process": "github:jspm/nodelibs-process@0.1.2", - "systemjs-json": "github:systemjs/plugin-json@0.1.0" - }, "npm:pixi.js@3.0.9": { "async": "npm:async@1.5.2", "brfs": "npm:brfs@1.4.3", @@ -394,20 +201,12 @@ System.config({ "url": "github:jspm/nodelibs-url@0.1.0" }, "npm:process-nextick-args@1.0.6": { - "process": "github:jspm/nodelibs-process@0.1.2" + "process": "github:jspm/nodelibs-process@0.1.2", + "systemjs-json": "github:systemjs/plugin-json@0.1.0" }, "npm:process@0.11.2": { "assert": "github:jspm/nodelibs-assert@0.1.0" }, - "npm:public-encrypt@4.0.0": { - "bn.js": "npm:bn.js@4.10.0", - "browserify-rsa": "npm:browserify-rsa@4.0.0", - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "create-hash": "npm:create-hash@1.1.2", - "crypto": "github:jspm/nodelibs-crypto@0.1.0", - "parse-asn1": "npm:parse-asn1@5.0.0", - "randombytes": "npm:randombytes@2.0.2" - }, "npm:punycode@1.3.2": { "process": "github:jspm/nodelibs-process@0.1.2" }, @@ -426,11 +225,6 @@ System.config({ "process": "github:jspm/nodelibs-process@0.1.2", "through2": "npm:through2@2.0.0" }, - "npm:randombytes@2.0.2": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "crypto": "github:jspm/nodelibs-crypto@0.1.0", - "process": "github:jspm/nodelibs-process@0.1.2" - }, "npm:readable-stream@1.0.33": { "buffer": "github:jspm/nodelibs-buffer@0.1.0", "core-util-is": "npm:core-util-is@1.0.2", @@ -476,16 +270,6 @@ System.config({ "process": "github:jspm/nodelibs-process@0.1.2", "url": "github:jspm/nodelibs-url@0.1.0" }, - "npm:ripemd160@1.0.1": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "process": "github:jspm/nodelibs-process@0.1.2" - }, - "npm:sha.js@2.4.4": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "fs": "github:jspm/nodelibs-fs@0.1.2", - "inherits": "npm:inherits@2.0.1", - "process": "github:jspm/nodelibs-process@0.1.2" - }, "npm:source-map@0.1.43": { "amdefine": "npm:amdefine@1.0.0", "fs": "github:jspm/nodelibs-fs@0.1.2", @@ -529,19 +313,12 @@ System.config({ "util": "github:jspm/nodelibs-util@0.1.0", "xtend": "npm:xtend@4.0.1" }, - "npm:ultron@1.0.2": { - "events": "github:jspm/nodelibs-events@0.1.1" - }, "npm:url@0.10.3": { "assert": "github:jspm/nodelibs-assert@0.1.0", "punycode": "npm:punycode@1.3.2", "querystring": "npm:querystring@0.2.0", "util": "github:jspm/nodelibs-util@0.1.0" }, - "npm:utf-8-validate@1.1.0": { - "bindings": "npm:bindings@1.2.1", - "nan": "npm:nan@1.8.4" - }, "npm:util-deprecate@1.0.2": { "util": "github:jspm/nodelibs-util@0.1.0" }, @@ -549,28 +326,12 @@ System.config({ "inherits": "npm:inherits@2.0.1", "process": "github:jspm/nodelibs-process@0.1.2" }, - "npm:vm-browserify@0.0.4": { - "indexof": "npm:indexof@0.0.1" - }, - "npm:ws@0.7.2": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "bufferutil": "npm:bufferutil@1.1.0", - "crypto": "github:jspm/nodelibs-crypto@0.1.0", - "events": "github:jspm/nodelibs-events@0.1.1", - "http": "github:jspm/nodelibs-http@1.7.1", - "https": "github:jspm/nodelibs-https@0.1.0", - "options": "npm:options@0.0.6", - "process": "github:jspm/nodelibs-process@0.1.2", - "stream": "github:jspm/nodelibs-stream@0.1.0", - "tls": "github:jspm/nodelibs-tls@0.1.0", - "ultron": "npm:ultron@1.0.2", - "url": "github:jspm/nodelibs-url@0.1.0", - "utf-8-validate": "npm:utf-8-validate@1.1.0", - "util": "github:jspm/nodelibs-util@0.1.0", - "zlib": "github:jspm/nodelibs-zlib@0.1.0" - }, "npm:xtend@2.1.2": { - "object-keys": "npm:object-keys@0.4.0" + "object-keys": "npm:object-keys@0.4.0", + "systemjs-json": "github:systemjs/plugin-json@0.1.0" + }, + "npm:xtend@4.0.1": { + "systemjs-json": "github:systemjs/plugin-json@0.1.0" } } }); diff --git a/gulpfile.js b/gulpfile.js index 57b6668..b1af9c4 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -9,6 +9,7 @@ var jshint = require('gulp-jshint'); var runSeq = require('run-sequence'); var stylish = require('jshint-stylish'); var jscs = require('gulp-jscs'); +var sourcemaps = require('gulp-sourcemaps'); var browserSync = require('browser-sync').create(); var mocha = require('gulp-mocha'); @@ -27,7 +28,9 @@ gulp.task('html', function () { gulp.task('js', function () { gulp.src(['client/js/main.js']) + .pipe(sourcemaps.init()) .pipe(jspm({ selfExecutingBundle: true })) + .pipe(sourcemaps.write('.')) .pipe(gulp.dest('build/js/')); }); diff --git a/package.json b/package.json index 9dd11cc..974926c 100644 --- a/package.json +++ b/package.json @@ -8,42 +8,36 @@ "author": "NEXT", "license": "ISC", "devDependencies": { - "browser-sync": "^2.11.1", - "chai": "^3.5.0", - "gulp": "^3.9.0", - "gulp-cssnano": "^2.1.0", - "gulp-htmlmin": "^1.3.0", - "gulp-jscs": "^3.0.2", - "gulp-jshint": "^2.0.0", - "gulp-jspm": "^0.5.6", - "gulp-mocha": "^2.2.0", - "gulp-rename": "^1.2.2", - "jshint": "^2.9.1", - "jshint-stylish": "^2.1.0", - "jspm": "^0.16.25", - "mocha": "^2.4.5", - "run-sequence": "^1.1.5" + "browser-sync": "2.11.1", + "chai": "3.5.0", + "gulp": "3.9.0", + "gulp-cssnano": "2.1.0", + "gulp-htmlmin": "1.3.0", + "gulp-jscs": "3.0.2", + "gulp-jshint": "2.0.0", + "gulp-jspm": "0.5.6", + "gulp-mocha": "2.2.0", + "gulp-rename": "1.2.2", + "gulp-sourcemaps": "1.6.0", + "jshint": "2.9.1", + "jshint-stylish": "2.1.0", + "jspm": "0.16.25", + "mocha": "2.4.5", + "run-sequence": "1.1.5" }, "jspm": { "dependencies": { - "dat-gui": "npm:dat-gui@^0.5.0", - "events": "npm:events@^1.1.0", - "heroandtn3/agario-client": "github:heroandtn3/agario-client@workaround", - "pixi.js": "npm:pixi.js@^3.0.9", - "stats.js": "npm:stats.js@^0.0.14-master" + "dat-gui": "npm:dat-gui@0.5.0", + "events": "npm:events@1.1.0", + "http": "github:jspm/nodelibs-http@1.7.1", + "https": "github:jspm/nodelibs-https@0.1.0", + "pixi.js": "npm:pixi.js@3.0.9", + "stats.js": "npm:stats.js@0.0.14-master" }, "devDependencies": { - "babel": "npm:babel-core@^5.8.24", - "babel-runtime": "npm:babel-runtime@^5.8.24", - "core-js": "npm:core-js@^1.1.4" - }, - "overrides": { - "github:heroandtn3/agario-client@workaround": { - "registry": "npm", - "map": { - "dns": "@empty" - } - } + "babel": "npm:babel-core@5.8.24", + "babel-runtime": "npm:babel-runtime@5.8.24", + "core-js": "npm:core-js@1.1.4" } } } From 6993ccfaba3f217d6b64377a65215b367c6d481d Mon Sep 17 00:00:00 2001 From: Sang Hero Date: Sat, 19 Mar 2016 16:11:49 +0700 Subject: [PATCH 2/3] NEXT-5 Use Buffer from jspm --- .jshintrc | 1 + client/js/agario-client/Packet.js | 2 ++ client/js/agario-client/client.js | 14 +++++++------- config.js | 1 + package.json | 1 + 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.jshintrc b/.jshintrc index 677a01b..107ab01 100644 --- a/.jshintrc +++ b/.jshintrc @@ -5,5 +5,6 @@ "expr": true, "esnext": true, "globals": { + "console": false } } diff --git a/client/js/agario-client/Packet.js b/client/js/agario-client/Packet.js index a964889..0897aa5 100644 --- a/client/js/agario-client/Packet.js +++ b/client/js/agario-client/Packet.js @@ -1,5 +1,7 @@ 'use strict'; +import { Buffer } from 'buffer'; + export default class Packet { constructor(e) { diff --git a/client/js/agario-client/client.js b/client/js/agario-client/client.js index d29f421..dc710bc 100644 --- a/client/js/agario-client/client.js +++ b/client/js/agario-client/client.js @@ -1,7 +1,7 @@ 'use strict'; import EventEmitter from 'events'; - +import { Buffer } from 'buffer'; import Packet from './Packet'; import servers from './servers'; import Account from './Account'; @@ -44,7 +44,7 @@ Client.prototype = { if (this.agent) opt.agent = this.agent; if (this.local_address) opt.localAddress = this.local_address; - this.ws = new WebSocket(server, null, opt); + this.ws = new WebSocket(server); this.ws.binaryType = 'arraybuffer'; this.ws.onopen = this.onConnect.bind(this); this.ws.onmessage = this.onMessage.bind(this); @@ -101,7 +101,7 @@ Client.prototype = { this.send(buf); var i; - + console.log(this.key); if (this.key) { buf = new Buffer(1 + this.key.length); buf.writeUInt8(80, 0); @@ -141,10 +141,12 @@ Client.prototype = { onMessage: function (e) { var packet = new Packet(e); + if (!packet.length) { return this.onPacketError(packet, new Error('Empty packet received')); } var packet_id = packet.readUInt8(); + console.log(packet_id); var processor = this.processors[packet_id]; if (!processor) return this.log('[warning] unknown packet ID(' + packet_id + '): ' + packet.toString()); @@ -156,7 +158,7 @@ Client.prototype = { this.emitEvent('message', packet); try { - processor(this, packet); + processor.call(this, this, packet); }catch (err) { this.onPacketError(packet, err); } @@ -520,9 +522,7 @@ Client.prototype = { try { this.emit.apply(this, args); } catch (e) { - process.nextTick(function () { - throw e; - }); + throw e; } }, diff --git a/config.js b/config.js index 4d8384b..035d469 100644 --- a/config.js +++ b/config.js @@ -16,6 +16,7 @@ System.config({ map: { "babel": "npm:babel-core@5.8.35", "babel-runtime": "npm:babel-runtime@5.8.35", + "buffer": "github:jspm/nodelibs-buffer@0.1.0", "core-js": "npm:core-js@1.2.6", "dat-gui": "npm:dat-gui@0.5.0", "events": "npm:events@1.1.0", diff --git a/package.json b/package.json index 974926c..966e8e7 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ }, "jspm": { "dependencies": { + "buffer": "github:jspm/nodelibs-buffer@^0.1.0", "dat-gui": "npm:dat-gui@0.5.0", "events": "npm:events@1.1.0", "http": "github:jspm/nodelibs-http@1.7.1", From 146e06f58867a02ca3298b01fc60b504c63eaa38 Mon Sep 17 00:00:00 2001 From: Sang Hero Date: Sat, 19 Mar 2016 16:28:17 +0700 Subject: [PATCH 3/3] NEXT-5 Change initial key (pakect ID 255) --- client/js/agario-client/client.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/client/js/agario-client/client.js b/client/js/agario-client/client.js index dc710bc..fa0bdee 100644 --- a/client/js/agario-client/client.js +++ b/client/js/agario-client/client.js @@ -97,11 +97,10 @@ Client.prototype = { buf = new Buffer(5); buf.writeUInt8(255, 0); - buf.writeUInt32LE(2200049715, 1); + buf.writeUInt32LE(154669603, 1); this.send(buf); var i; - console.log(this.key); if (this.key) { buf = new Buffer(1 + this.key.length); buf.writeUInt8(80, 0); @@ -141,12 +140,10 @@ Client.prototype = { onMessage: function (e) { var packet = new Packet(e); - if (!packet.length) { return this.onPacketError(packet, new Error('Empty packet received')); } var packet_id = packet.readUInt8(); - console.log(packet_id); var processor = this.processors[packet_id]; if (!processor) return this.log('[warning] unknown packet ID(' + packet_id + '): ' + packet.toString());