· 7 years ago · Sep 02, 2018, 05:58 PM
1var Packet = require('./packet');
2var request = require('request');
3var LastMsg;
4var SpamBlock;
5
6function PacketHandler(gameServer, socket) {
7 this.gameServer = gameServer;
8 this.socket = socket;
9 // Detect protocol version - we can do something about it later
10 this.protocol = 0;
11 this.pressQ = false;
12 this.pressW = false;
13 this.pressSpace = false;
14}
15
16module.exports = PacketHandler;
17
18PacketHandler.prototype.handleMessage = function (message) {
19 function stobuf(buf) {
20 var length = buf.length;
21 var arrayBuf = new ArrayBuffer(length);
22 var view = new Uint8Array(arrayBuf);
23 for (var i = 0; i < length; i++) {
24 view[i] = buf[i];
25 }
26 return view.buffer;
27 }
28
29 // Discard empty messages
30 if (message.length == 0) {
31 return;
32 }
33
34 var buffer = stobuf(message);
35 var view = new DataView(buffer);
36 var packetId = view.getUint8(0, true);
37 this.socket.sendPacket(new Packet.Countdown(this.gameServer.countdown));
38 switch (packetId) {
39 case 0:
40 // Set Nickname
41 var nick = '';
42 for (var i = 1, llen = view.byteLength; i < llen; i += 2) {
43 var charCode = view.getUint16(i, true);
44 if (charCode == 0) {
45 break;
46 }
47 nick += String.fromCharCode(charCode);
48 }
49 this.setNickname(nick);
50 break;
51 case 1:
52 // Spectate mode
53 if (this.socket.playerTracker.cells.length <= 0) {
54 this.gameServer.switchSpectator(this.socket.playerTracker);
55 this.socket.playerTracker.spectate = true;
56 }
57 break;
58 case 16:
59 // Mouse coordinates
60 var client = this.socket.playerTracker;
61 if(!client.freeMouse) break;
62 if (view.byteLength == 13) {
63 client.mouse.x = view.getInt32(1, true);
64 client.mouse.y = view.getInt32(5, true);
65 } else if (view.byteLength == 9) {
66 client.mouse.x = view.getInt16(1, true);
67 client.mouse.y = view.getInt16(3, true);
68 } else if (view.byteLength == 21) {
69 client.mouse.x = view.getFloat64(1, true);
70 client.mouse.y = view.getFloat64(9, true);
71 }
72 break;
73 case 17:
74 // Space Press - Split cell
75 this.pressSpace = true;
76 break;
77 case 18:
78 // Q Key Pressed
79 this.pressQ = true;
80 break;
81 case 19:
82 // Q Key Released
83 break;
84 case 21:
85 // W Press - Eject mass
86 this.pressW = true;
87 break;
88 case 80:
89 // Cookie Code from Agar.io
90 // for (var message = '', i = 1, llen = view.byteLength; i < llen; i++) {
91 // message += String.fromCharCode(view.getUint8(i, !0));
92 // }
93 break;
94 case 82:
95 // User login access token
96 break;
97 case 90:
98 // Send Server Info
99 this.socket.sendPacket(new Packet.ServerInfo(process.uptime().toFixed(0), this.gameServer.sinfo.humans, this.gameServer.config.borderRight, this.gameServer.nodes.length, this.gameServer.config.serverGamemode));
100 break;
101 case 95:
102 var token = '',
103 offset = 2,
104 maxLen = 1000 * 10;
105 for (var i = offset, llen = view.byteLength; i < llen && i <= maxLen; i += 2) {
106 token += String.fromCharCode(view.getUint8(i, !0))[0];
107 const secretKey = "6LeMom0UAAAAAJMBAmb7eWtiJS17DwDBqPl0eOBw";
108 request.post("https://www.google.com/recaptcha/api/siteverify?secret=" + secretKey + "&response=" + token, (err, res, body) => {
109 const data = JSON.parse(body)
110 if (data.success) {
111 this.socket.playerTracker.captchaVerified = true;
112 } else {
113 ws.close;
114 }
115 })
116 }
117
118 console.log(token);
119 break;
120 case 99:
121 // Chat
122 var message = "",
123 maxLen = this.gameServer.config.chatMaxMessageLength * 2,
124 offset = 2,
125 flags = view.getUint8(1);
126
127 if (flags & 2) {
128 offset += 4;
129 }
130 if (flags & 4) {
131 offset += 8;
132 }
133 if (flags & 8) {
134 offset += 16;
135 }
136
137 for (var i = offset, llen = view.byteLength; i < llen && i <= maxLen; i += 2) {
138 var charCode = view.getUint16(i, true);
139 if (charCode == 0) {
140 break;
141 }
142 message += String.fromCharCode(charCode);
143 }
144
145 // Remove trailing spaces
146 message = message.trim();
147 if (message == "") {
148 break;
149 }
150
151 // Get player name
152 var wname = this.socket.playerTracker.name;
153 if (wname == "") wname = "Spectator";
154
155 // Rcon if enabled
156 if (this.gameServer.config.serverAdminPass != '') {
157 if ( this.rcon(message, wname) == true ) break;
158 }
159
160 // Spam chat delay
161 if ((this.gameServer.time - this.socket.playerTracker.cTime) < this.gameServer.config.chatIntervalTime) {
162 var time = 1 + Math.floor(((this.gameServer.config.chatIntervalTime - (this.gameServer.time - this.socket.playerTracker.cTime)) / 1000) % 60);
163 var packet = new Packet.BroadCast("Wait " + time + " seconds more, before you can send a message.");
164 this.socket.sendPacket(packet);
165 break;
166 }
167 this.socket.playerTracker.cTime = this.gameServer.time;
168
169 // Location to chat
170 if(message == "pos") message = this.MyPos();
171
172 // Repeating chat block
173 if (message == LastMsg) {
174 ++SpamBlock;
175 if (SpamBlock > 5) this.socket.close();
176 break;
177 }
178 LastMsg = message;
179 SpamBlock = 0;
180
181 // Profanity filter
182 message = this.WordScan(message);
183
184 // Chat logging
185 if (this.gameServer.config.chatToConsole == 1) {
186 console.log("\u001B[36m" + wname + ": \u001B[0m" + message);
187 }
188 if (this.gameServer.config.serverLogToFile) {
189 var fs = require('fs');
190 var wstream = fs.createWriteStream('logs/chat.log', {flags: 'a'});
191 wstream.write('[' + this.gameServer.formatTime() + '] ' + wname + ': ' + message + '\n');
192 wstream.end();
193 }
194
195 // Send to all clients (broadcast)
196 var packet = new Packet.Chat(this.socket.playerTracker, message);
197 for (var i = 0, llen = this.gameServer.clients.length; i < llen; i++) {
198 this.gameServer.clients[i].sendPacket(packet);
199 }
200 break;
201 case 102:
202 // Some score stuff it seems send by Agar.io
203 break;
204 case 254:
205 // Handshake setUint32(1, 5, !0)
206 break;
207 case 255:
208 // Connection Start
209 if (view.byteLength == 5) {
210 var c = this.gameServer.config;
211
212 // Boot Player if Server Full
213 if (this.gameServer.sinfo.players > c.serverMaxConnections) {
214 this.socket.sendPacket(new Packet.ServerMsg(93));
215 this.socket.close();
216 }
217 this.socket.sendPacket(new Packet.SetBorder(c.borderLeft, c.borderRight, c.borderTop, c.borderBottom));
218 this.socket.sendPacket(new Packet.ServerInfo(process.uptime().toFixed(0), this.gameServer.sinfo.humans, c.borderRight, c.foodMaxAmount, c.serverGamemode));
219 }
220 break;
221 default:
222 console.log("Unknown Packet ID: " + packetId);
223 break;
224 }
225};
226
227PacketHandler.prototype.WordScan = function(line) {
228 // a few bad words...
229 line = line.replace(/isis/gi, "kiss");
230 line = line.replace(/faggot/gi, "cloud");
231 line = line.replace(/hitler/gi, "coyote");
232 line = line.replace(/nazi/gi, "rat");
233 line = line.replace(/cock/gi, "broom");
234 line = line.replace(/fuck/gi, "meow");
235 line = line.replace(/dick/gi, "tree");
236 line = line.replace(/bitch/gi, "cat");
237 line = line.replace(/shit/gi, "mouse");
238 line = line.replace(/cunt/gi, "heat");
239 line = line.replace(/slut/gi, "love");
240 line = line.replace(/weed/gi, "flower");
241 line = line.replace(/gay/gi, "fly");
242 line = line.replace(/penis/gi, "daddy");
243 line = line.replace(/nigger/gi, "tigger");
244 line = line.replace(/nigga/gi, "tigger");
245 line = line.replace(/porn/gi, "milk");
246 line = line.replace(/cocaine/gi, "candy");
247 line = line.replace(/servertime/gi, "time now is " + this.gameServer.formatTime());
248
249 // Stop Stealing My BOT's Tags already!
250 line = line.replace(/\[(BOT)\]/gi, "[2ch]");
251 line = line.replace(/<BOT>/gi, "<2ch>");
252
253 // Block http:// in chat/name
254 line = line.replace(/.*?:\/\//g, "");
255
256 return line;
257};
258
259PacketHandler.prototype.rcon = function(message, wname) {
260 var passkey = "/rcon " + this.gameServer.config.serverAdminPass + " ";
261 if (message.substr(0, passkey.length) == passkey) {
262 var cmd = message.substr(passkey.length, message.length);
263 console.log("\u001B[36m" + wname + ": \u001B[0missued a remote console command: " + cmd);
264 var split = cmd.split(" "),
265 first = split[0].toLowerCase(),
266 execute = this.gameServer.commands[first];
267 if (typeof execute != 'undefined') {
268 execute(this.gameServer, split);
269 } else {
270 console.log("Invalid Command!");
271 }
272 return true;
273 } else if (message.substr(0, 6) == "/rcon ") {
274 console.log("\u001B[36m" + wname + ": \u001B[0missued a remote console command but used a wrong pass key!");
275 return true;
276 }
277 return false;
278};
279
280PacketHandler.prototype.MyPos = function() {
281 var clientpos = this.socket.playerTracker.centerPos;
282 var msizex = (this.gameServer.config.borderRight - this.gameServer.config.borderLeft) / 5;
283 var msizey = (this.gameServer.config.borderBottom - this.gameServer.config.borderTop) / 5;
284
285 var pX = "1";
286 var shortX = "left";
287 if( clientpos.x > msizex ) { pX = "2"; shortX = "left"; }
288 if( clientpos.x > (msizex * 2)) { pX = "3"; shortX = "middle";}
289 if( clientpos.x > (msizex * 3)) { pX = "4"; shortX = "right"; }
290 if( clientpos.x > (msizex * 4)) { pX = "5"; shortX = "right"; }
291
292 var pY = "A";
293 var shortY = "top";
294 if( clientpos.y > msizey ) { pY = "B"; shortY = "top"; }
295 if( clientpos.y > (msizey * 2)) { pY = "C"; shortY = "middle"; }
296 if( clientpos.y > (msizey * 3)) { pY = "D"; shortY = "bottom"; }
297 if( clientpos.y > (msizey * 4)) { pY = "E"; shortY = "bottom"; }
298
299 var short = "";
300 if(shortY == "middle" && shortX == "middle") {
301 short = "center @ ";
302 } else {
303 short = shortY + " " + shortX + " @ ";
304 }
305
306 return "i am at " + clientpos.x + " : " + clientpos.y + " -" + short + pY + pX + "-";
307};
308
309PacketHandler.prototype.setNickname = function(newNick) {
310 var client = this.socket.playerTracker;
311 if (client.cells.length < 1) {
312 if (typeof this.socket.remoteAddress != 'undefined' && this.socket.remoteAddress != 'undefined') {
313 newNick = this.WordScan(newNick);
314 }
315 // Set name first
316 var newSkin = "";
317 if (newNick != null && newNick.length != 0) {
318 if (newNick[0] == "<") {
319 var n = newNick.indexOf(">", 1);
320 if (n != -1) {
321 newSkin = "%" + newNick.slice(1, n);
322 newNick = newNick.slice(n+1);
323 }
324 } else if (newNick[0] == "|") {
325 var n = newNick.indexOf("|", 1);
326 if (n != -1) {
327 newSkin = ":http://" + newNick.slice(1, n);
328 newNick = newNick.slice(n+1);
329 }
330 }
331 }
332
333 // Remove spaces incase there where any inbetween skin and name
334 newNick = newNick.trim();
335
336 if (newNick.length > (this.gameServer.config.playerMaxNickLength + 1)) {
337 newNick = newNick.slice(0, (this.gameServer.config.playerMaxNickLength + 1));
338 }
339
340 // No name or weird name, lets call it Cell + pid Number
341 if (newNick == "" || newNick == "Unregistered" || newNick == "Un Named") {
342 newNick = "HfW" + client.pID;
343 }
344
345 if (this.gameServer.gameMode.haveTeams) {
346 client.setName(" "+newNick+" "); //trick to disable skins in teammode
347 } else {
348 client.setName(newNick);
349 }
350
351 if (newSkin) {
352 this.socket.saveSkin = newSkin;
353 } else if (this.socket.saveSkin) {
354 newSkin = this.socket.saveSkin;
355 }
356
357 client.setSkin(newSkin);
358
359 // If client has no cells... then spawn a player
360 this.gameServer.gameMode.onPlayerSpawn(this.gameServer,client);
361
362 // Turn off spectate mode
363 client.spectate = false;
364 }
365};