Coverage

98%
480
471
9

/home/lesterpig/workspace/openparty/lib/attrs.js

100%
1
1
0
LineHitsSource
11module.exports = {
2
3 name: {m: true, t: "String"},
4 start: {m: true, t: "Function"},
5 minPlayers: {m: true, t: "Integer"},
6 maxPlayers: {m: true, t: "Integer"},
7
8 init: {t: "Function"},
9 firstStage: {t: "String"},
10 parameters: {t: "Array"},
11 stages: {t: "Object"},
12 processMessage: {t: "Function"},
13 onDisconnect: {t: "Function"},
14 version: {t: "String"},
15 description: {t: "String"},
16 opVersion: {t: "String"},
17 css: {t: "Array"}
18
19};
20

/home/lesterpig/workspace/openparty/lib/loader.js

100%
73
73
0
LineHitsSource
11var path = require('path');
21var fs = require('fs');
31var color = require('colors');
41var sem = require('semver');
51var utils = require('./utils');
61var attrs = require('./attrs');
7
81module.exports = function(basePath, callback) {
9
108 if(!basePath)
111 basePath = path.join(__dirname, "..", "data");
128 if(!callback)
131 callback = function(){};
14
158 var gametypes = {};
16
178 fs.readdir(basePath, function(err, files) {
18
198 if(err) {
201 return callback( "!! Unable to load game definitions\n".red +
21 " Install gameplay definitions in data/ subdirectory\n".red +
22 (" Was: " + err).red, null);
23 }
24
257 var ok = false;
26
277 files.forEach(function(filePath) {
2831 if(fs.statSync(path.join(basePath, filePath)).isDirectory()) {
29
3021 var modulePath = path.join(basePath, filePath, "definition.js");
3121 if(!fs.existsSync(modulePath))
3210 return;
33
3411 if((module = checkFile(modulePath))) {
355 ok = true;
365 gametypes[filePath] = module;
37
38 // Has public files ?
395 var publicPath = path.join(basePath, filePath, "public");
405 if(fs.existsSync(publicPath)) {
415 __app.use(__app.express.static(publicPath));
42 }
43 }
44 }
45 });
46
477 if(!ok) {
482 return callback("!! No gameplay definition was correct. Aborting.".red, null);
49 }
50
515 callback(null, gametypes);
52
53 });
54};
55
561var checkFile = function(path) {
57
5811 var errorLog = [];
59
6011 try {
6111 module = require(path);
6210 var instance = new module();
63
649 checkMissingAttributes(instance, errorLog);
659 checkWrongAttributes(instance, errorLog);
66
679 if(errorLog.length === 1) {
682 throw new Error("One semantic failure");
697 } else if(errorLog.length > 1) {
702 throw new Error(errorLog.length + " semantic failures");
71 }
72
73 // Everything is ok!
745 return module;
75 } catch(e) {
766 console.error(("~~ Cannot load '" + path + "'\n " + e).yellow)
776 errorLog.forEach(function(a) {
7810 console.error((" - " + a).gray.italic);
79 });
806 return null;
81 }
82};
83
841var checkMissingAttributes = function(instance, errorLog) {
85
869 for(var attr in attrs) {
87126 if(!attrs[attr].m) {
8890 continue;
89 }
90
9136 if(!instance[attr]) {
924 errorLog.push("Missing '" + attr + "' mandatory attribute (" + attrs[attr].t + ")");
93 }
94 }
95
96};
97
981var checkType = function(e, t) {
99
10069 var fn;
10169 switch(t) {
10240 case "String": fn = utils.isString; break;
10346 case "Function": fn = utils.isFunction; break;
10432 case "Integer": fn = utils.isInteger; break;
10512 case "Array": fn = utils.isArray; break;
1068 case "Object": fn = utils.isObject; break;
107 }
10869 return fn(e);
109
110};
111
1121var checkWrongAttributes = function(instance, errorLog) {
113
1149 for(var attr in attrs) {
115126 if(instance[attr] && !checkType(instance[attr], attrs[attr].t)) {
1162 errorLog.push("'" + attr + "' must be of type (" + attrs[attr].t + ")");
117 }
118 }
119
1209 if(instance.maxPlayers <= 0) {
1211 errorLog.push("'maxPlayers' must be positive");
122 }
123
1249 if(instance.minPlayers <= 0) {
1251 errorLog.push("'minPlayers' must be positive");
126 }
127
1289 if(instance.maxPlayers < instance.minPlayers) {
1291 errorLog.push("'minPlayers' is greater than 'maxPlayers'");
130 }
131
1329 if(instance.opVersion && !sem.satisfies(__version, instance.opVersion)) {
1331 errorLog.push("This module is not ready for this version of OpenParty (" + __version + " does not satisfy " + instance.opVersion + ")");
134 }
135}
136

/home/lesterpig/workspace/openparty/lib/players.js

98%
97
96
1
LineHitsSource
11var utils = require("/home/lesterpig/workspace/openparty/lib/./utils.js");
2
31var Player = function(socket, room) {
4
5 /**
6 * roles = {
7 * <name>: {channels: {}, actions: {}},
8 * ...
9 * }
10 *
11 */
128 this.roles = {};
13
148 this.channels = {};
158 this.actions = {};
16
178 this.socket = socket; // circular
188 this.room = room; // circular
198 this.username = socket.username;
20
21};
22
2323Player.prototype.join = function(channel) { this.socket.join("room_" + this.room.id + "_" + channel); };
246Player.prototype.leave = function(channel) { this.socket.leave("room_" + this.room.id + "_" + channel); };
25
261Player.prototype.setRole = function(role, value) {
275 if(!value && this.roles[role]) {
28 // Remove all registered channels
291 for(var channel in this.roles[role].channels) {
302 if(this.roles[role].channels[channel].r && !this.channels[channel]) {
312 this.leave(channel);
32 }
33 }
344 } else if(value) {
35 // Join all channels
363 for(var channel in value.channels) {
375 if(value.channels[channel].r) {
384 this.join(channel);
39 }
40 }
41 }
425 setAttributeObject(this, "roles", role, value);
435 this.sendWriteChannels();
44};
45
461Player.prototype.setAction = function(name, value) {
473 setAttributeObject(this, "actions", name, value);
48};
49
501Player.prototype.setChannel = function(name, rights, silent) {
51
5220 if(!rights) {
531 if(this.channels[name]) {
541 this.leave(name);
551 delete this.channels[name];
56 // Refreshing channels
571 for(var role in this.roles) {
581 for(var channel in this.roles[role].channels) {
592 if(channel === name && this.roles[role].channels[channel].r)
601 this.join(channel);
61 }
62 }
63 }
64 }
65
66 else {
6719 if(rights.r) {
6817 this.join(name);
69 }
70 else {
712 this.leave(name);
72 }
7319 this.channels[name] = rights;
74 }
7520 if(!silent) {
764 this.sendWriteChannels();
77 }
78};
79
801Player.prototype.getWriteChannels = function() {
8134 var channels = {};
82
8334 for(var role in this.roles) {
8423 for(var channel in this.roles[role].channels) {
8541 if(this.roles[role].channels[channel].w) {
8623 channels[channel] = this.roles[role].channels[channel];
87 }
88 }
89 }
90
9134 for(var channel in this.channels) { // override "default" behavior
9280 if(this.channels[channel].w) {
9339 channels[channel] = this.channels[channel];
94 }
95 else {
9641 delete channels[channel];
97 }
98 }
99
10034 return channels;
101};
102
1031Player.prototype.sendWriteChannels = function() {
10417 return this.emit("setAllowedChannels", this.getWriteChannels());
105};
106
1071Player.prototype.getAvailableActions = function(clone) {
10835 var output = {};
109
110 // role actions
11135 for(var role in this.roles) {
11225 for(var action in this.roles[role].actions) {
11376 if(this.roles[role].actions[action].isAvailable(this)) {
11471 output[action] = this.roles[role].actions[action];
115 }
116 }
117 }
118
119 // personal actions (override)
12035 for(var action in this.actions) {
1216 if(this.actions[action].isAvailable && this.actions[action].isAvailable(this)) {
1225 output[action] = this.actions[action];
123 } else {
1241 delete output[action];
125 }
126 }
127
12835 for(var action in output) {
12975 if(clone) {
13023 output[action] = {
131 type: output[action].type,
132 options: output[action].options
133 };
134 }
135
13675 processActionOptions(output[action], this.room);
137 }
138
13935 return output;
140};
141
1421Player.prototype.sendAvailableActions = function() {
14320 return this.emit("setAvailableActions", this.getAvailableActions(true));
144};
145
1461Player.prototype.emit = function(event, data) {
14738 this.socket.emit(event,data);
14838 return true;
149};
150
1511Player.prototype.message = function(m) {
1520 this.emit("chatMessage", {message: m});
153};
154
1551module.exports = {
156
157 init: function(room) {
1582 room.players.forEach(function(p) {
1598 p.player = new Player(p, room);
1608 p.player.setChannel("general", {r:true, w:true, n:"General"}, true);
1618 p.player.setChannel("player-" + p.player.username, {r: true, w: false}, true);
1628 p.player.sendWriteChannels();
163 });
164 },
165
166 Player: Player
167
168};
169
170/** PRIVATE FUNCTIONS **/
171
1721function setAttributeObject(p, attr, name, value) {
1738 if(value === null || value === undefined) {
1743 delete p[attr][name];
175 }
176
177 else {
1785 p[attr][name] = value;
179 }
180}
181
1821function processActionOptions(action, room) {
183
18475 switch(action.type) {
185
186 case "select":
187
18853 if(!action.options.choices) {
1891 action.options.choices = "players";
190 }
191
19253 if(utils.isString(action.options.choices)) {
193
19419 var out = [];
19519 room.players.forEach(function(e) {
19676 out.push(e.username);
197 });
19819 action.options.safeChoices = out;
199
20034 } else if(Array.isArray(action.options.choices)) {
20119 action.options.safeChoices = action.options.choices;
202 } else {
20315 action.options.safeChoices = action.options.choices(room, this);
204 }
205
20653 break;
207
208 default:
20922 break;
210 }
211
212}
213

/home/lesterpig/workspace/openparty/lib/rooms.js

98%
191
189
2
LineHitsSource
11var utils = require("/home/lesterpig/workspace/openparty/lib/./utils.js");
21var players = require("/home/lesterpig/workspace/openparty/lib/./players.js");
31var Player = players.Player;
4
5
61var Room = function(name, password, gameplay) {
7
83 this.isRoom = true;
93 this.id = utils.randomString(20); // TODO make it better...
103 this.players = [];
113 this.name = name;
123 this.size = gameplay.minPlayers;
133 this.creationDate = new Date();
143 this.password = password;
15
163 this.gameplay = gameplay;
173 this.gameplay.room = this; // circular
18
19 // Stages
203 this.started = false;
213 this.timeout = null;
223 this.currentStage = null;
23
243 if(this.gameplay.init) {
253 this.gameplay.init(this);
26 }
27
28};
29
30/**
31 * Broadcast a message to several sockets
32 * @param {String} [channel]
33 * @param {String} event
34 * @param {*} [data]
35 */
361Room.prototype.broadcast = function(channel, event, data) {
37
3846 if(data === undefined && channel) {
3930 data = event;
4030 event = channel;
4130 channel = "";
4216 } else if(channel !== "") {
4312 channel = "_" + channel;
44 }
4546 __app.io.to("room_" + this.id + channel).emit(event, data);
46};
47
48/**
49 * Send more information about a player.
50 * Client-side, it will be displayed in players list.
51 *
52 * @param {String} [channel]
53 * @param {Object} player (socket or Player object)
54 * @param {String} value
55 */
561Room.prototype.playerInfo = function(channel, player, value) {
57
584 if(!value) {
592 if(channel instanceof Player) {
601 channel = channel.socket;
61 }
622 this.broadcast("playerInfo", {username: channel.username, value: player});
63 } else {
642 if(player instanceof Player) {
651 player = player.socket;
66 }
672 this.broadcast(channel, "playerInfo", {username: player.username, value: value});
68 }
69}
70
71/**
72 * Send a chat message to players (system message)
73 * @param {String} [channel]
74 * @param {String} message
75 */
761Room.prototype.message = function(channel, message) {
776 if(!message) {
784 this.broadcast("chatMessage", {message:channel});
79 }
80 else {
812 this.broadcast(channel, "chatMessage", {message:message});
82 }
83};
84
85/**
86 * Get public information about the room and its players
87 * @return {Object}
88 */
891Room.prototype.getPublicInfo = function() {
90
9135 var output = {};
92
9335 output.id = this.id;
9435 output.isRoom = true;
9535 output.name = this.name;
9635 output.players = [];
9735 output.size = this.size;
9835 output.started = this.started;
9935 output.password = !!this.password;
100
10135 for(var i = 0; i < this.players.length; i++) {
10272 output.players.push({username: this.players[i].username});
103 }
104
10535 var parameters = [];
10635 this.gameplay.parameters.forEach(function(p) {
10770 parameters.push({
108 name: p.name,
109 value: p.value,
110 help: p.help,
111 isBoolean: p.type === Boolean
112 });
113 });
114
11535 output.gameplay = {
116 name: this.gameplay.name,
117 description: this.gameplay.description,
118 parameters: parameters,
119 maxPlayers: this.gameplay.maxPlayers,
120 minPlayers: this.gameplay.minPlayers
121 };
122
12335 return output;
124
125};
126
127/**
128 * Set room size
129 * @param {Number} size
130 */
1311Room.prototype.setSize = function(size) {
132
1333 if(size >= this.gameplay.minPlayers && size <= this.gameplay.maxPlayers) {
1342 this.size = size;
1352 sendUpdateRoom(this);
136 }
137};
138
139/**
140 * Set room parameter
141 * @param {} parameter
142 * @param {*} value
143 * @param {Socket} socket
144 */
1451Room.prototype.setParameter = function(parameter, value, socket) {
146
147
1483 this.gameplay.parameters.forEach(function(e) {
1496 if(e.name === parameter) {
1502 e.value = e.type(value); //deal with it.
1512 sendUpdateRoom(this, socket);
1522 return;
153 }
154 }.bind(this));
155};
156
1571Room.prototype.sendMessage = function(channel, message, socket) {
158
15924 var allowed = false;
160
16124 if(channel === "preChat") {
1625 if(this.started) {
1631 return;
164 }
1654 allowed = true;
1664 channel = "";
167 } else {
16819 if(!this.started) {
1692 return;
170 }
17117 var channels = socket.player.getWriteChannels();
17217 allowed = (channels[channel] ? (true === channels[channel].w) : false);
173 }
174
17521 if(allowed) {
17615 socket.emit("messageSent");
17715 if(this.gameplay.processMessage && this.started) {
17811 message = this.gameplay.processMessage(channel, message, socket.player);
17911 if(!message) {
1804 return;
181 }
182 }
18311 this.broadcast(channel, "chatMessage", {message: message, sender: socket.username});
184 }
185};
186
1871Room.prototype.start = function() {
188
1892 players.init(this);
1902 this.gameplay.start(this, function(err) {
191
1922 if(err) {
1931 return this.broadcast("chatMessage", { message: err });
194 }
195
1961 this.started = true;
1971 sendUpdateRoom(this);
1981 this.broadcast("gameStarted");
199
2001 if(this.gameplay.firstStage) {
2011 this.nextStage(this.gameplay.firstStage);
202 }
203
204 }.bind(this));
205};
206
207/**
208 * End the current stage and start another one
209 * @param {String} stage The new stage name
210 * @param {Function} [callback]
211 */
2121Room.prototype.nextStage = function(stage, callback) {
213
2145 this.currentStage = stage;
215
2165 this.gameplay.stages[stage].start(this, function(err, duration) {
217
2185 this.setStageDuration(duration);
219
220 // Send actions to players
221
2225 this.players.forEach(function(player) {
22320 player.player.sendAvailableActions();
224 });
225
2265 if(callback) {
2271 callback(null);
228 }
229
230 }.bind(this));
231
232};
233
234/**
235 * End the current stage, without starting another one
236 */
2371Room.prototype.endStage = function() {
2381 clearTimeout(this.timeout);
2391 var endFn = this.gameplay.stages[this.currentStage].end;
2401 if(endFn)
2411 endFn(this, function() {});
242};
243
244/**
245 * Change current stage duration
246 * @param {Number} duration (sec)
247 */
2481Room.prototype.setStageDuration = function(duration) {
249
2506 clearTimeout(this.timeout);
251
2526 if(duration < 0) {
2533 this.broadcast("clearTimer");
2543 this.currentStageEnd = Infinity;
2553 return;
256 }
257
2583 this.currentStageEnd = new Date().getTime() + duration * 1000;
2593 this.broadcast("setTimer", duration);
2603 this.timeout = setTimeout(this.endStage.bind(this), duration * 1000);
261};
262
263/**
264 * @return Number Milliseconds before next stage. Can be "Infinity".
265 */
2661Room.prototype.getRemainingTime = function() {
267
2682 return this.currentStageEnd - new Date().getTime();
269
270};
271
272/**
273 * Get player object from username
274 * @param {String} username
275 * @return {Socket}
276 */
2771Room.prototype.resolveUsername = function(username) {
2783 for(var i = 0; i < this.players.length; i++) {
2797 if(this.players[i].username === username) {
2802 return this.players[i];
281 }
282 }
2831 return null;
284};
285
2861var rooms = module.exports = {
287
288 rooms: [],
289
290 getRooms: function() {
291
2921 var output = [];
2931 for(var i = 0; i < this.rooms.length; i++) {
2941 if(!this.rooms[i].started) {
2951 output.push(this.rooms[i].getPublicInfo());
296 }
297 }
298
2991 return output;
300 },
301
302 createRoom: function(name, password, type, socket) {
303
3044 if(!type || type === "default") {
3052 for(var i in __gametypes) {
3062 type = i;
3072 break;
308 }
309 }
310
3114 if(!__gametypes[type]) {
3121 return;
313 }
314
3153 var gameplay = new __gametypes[type]();
316
3173 var room = new Room(name, password, gameplay);
318
3193 this.rooms.push(room);
3203 __app.io.to("lobby").emit("roomCreated", room.getPublicInfo());
3213 this.joinRoom(room.id, password, socket);
322 },
323
324 getRoom: function(id) {
325
32612 for(var i = 0; i < this.rooms.length; i++) {
32712 if(this.rooms[i].id === id) {
32811 return this.rooms[i];
329 }
330 }
331
3321 return null;
333
334 },
335
336 joinRoom: function(id, password, socket) {
337
33812 var room = this.getRoom(id);
33912 if(!room) {
3401 return;
341 }
342
34311 if(room.players.length >= room.size) {
3441 return;
345 }
346
34710 if(room.password && room.password !== password) {
3480 socket.emit("invalidRoomPassword");
3490 return;
350 }
351
35210 if(room.players.indexOf(socket) < 0) {
35310 room.players.push(socket);
354 }
355
35610 sendUpdateRoom(room);
35710 socket.emit("roomJoined", room.getPublicInfo());
35810 socket.join("room_" + id);
35910 socket.currentRoom = room;
360
36110 room.broadcast("chatMessage", {message: "<span class='glyphicon glyphicon-ok-circle'></span> <strong>" + socket.username + "</strong> has joined the room"});
362
363 },
364
365 leaveRoom: function(socket) {
366
36713 var room = socket.currentRoom;
36813 if(!room) {
3694 return;
370 }
371
3729 var i = room.players.indexOf(socket);
3739 if(i < 0) {
3741 return;
375 }
376
3778 room.players.splice(i, 1);
378
3798 if(room.gameplay.onDisconnect && socket.player) {
3802 room.gameplay.onDisconnect(room, socket.player);
381 }
382
3838 if(!room.started && socket.username) {
3846 room.broadcast("chatMessage", {message: "<span class='glyphicon glyphicon-remove-circle'></span> <strong>" + socket.username + "</strong> has left the room"});
385 }
386
3878 if(room)
388
3898 if(room.players.length === 0) {
3902 this.removeRoom(room);
391 } else {
3926 sendUpdateRoom(room);
393 }
394
3958 socket.player = null;
3968 socket.currentRoom = null;
397
398 // Leave concerned socket rooms
399 // Buffered, because socket.rooms is dynamically updated by socket.io
4008 var regex = /^room\_/;
4018 var buffer = socket.rooms.filter(function(r) {
40217 return regex.test(r);
403 });
404
4058 try {
4068 buffer.forEach(function(r) {
4077 socket.leave(r);
408 });
4098 socket.emit("roomLeft");
410 } catch(e) {}
411
412 },
413
414 removeRoom: function(room) {
415
4162 for(var i = 0; i < this.rooms.length; i++) {
4172 if(this.rooms[i].id === room.id) {
4182 clearTimeout(this.rooms[i].timeout);
4192 this.rooms.splice(i, 1);
4202 __app.io.to("lobby").emit("roomRemoved", room.id);
4212 return;
422 }
423 }
424
425 }
426
427};
428
429/** PRIVATE FUNCTIONS **/
430
4311function sendUpdateRoom(room, socket) {
43221 if(!socket) {
43319 __app.io.to("lobby").emit("roomUpdated", room.getPublicInfo());
434 }
435 else {
4362 socket.broadcast.to("lobby").emit("roomUpdated", room.getPublicInfo());
437 }
438}
439

/home/lesterpig/workspace/openparty/lib/router.js

92%
85
79
6
LineHitsSource
11var utils = require("/home/lesterpig/workspace/openparty/lib/./utils");
21var rooms = require("/home/lesterpig/workspace/openparty/lib/./rooms");
31var git = require("git-repo-info");
4
5// we want to define this only one time
61var repo = git(".git");
71if(repo.branch) {
81 repo.url = require("/home/lesterpig/workspace/openparty/lib/../package.json").repository.url.replace(/\.git$/, "") + "/commit/" + repo.sha;
9}
10
111module.exports = function(app) {
12
13 /**
14 * ROOT
15 */
161 app.get("/", function(req, res) {
171 req.session.locale = req.getLocale();
181 res.render("index", {passwordRequired: __conf.password !== null });
19 });
20
21 /***
22 * ABOUT
23 */
241 app.get("/about", function(req, res) {
251 res.render("about", {repo: repo, version: __version, locales: __conf.locales, gamemodes: __staticGametypes });
26 });
27
28 /**
29 * IO : Ping
30 */
311 app.io.route("ping", function(socket) {
321 socket.volatile.emit("pong");
33 });
34
35 /**
36 * IO : Disconnect
37 */
381 app.io.route("disconnect", function(socket) {
39
404 var room = utils.isInGame(socket);
415 if(!room) return;
42
433 rooms.leaveRoom(socket);
44 });
45
46 /**
47 * IO : Login
48 */
491 app.io.route("login", function(socket, data) {
50
5118 var locale = socket.session.locale || __conf.defaultLocale;
52
5318 if(data.password !== __conf.password && __conf.password !== null || !data.username) {
544 return socket.emit("loginResult", {err: __i18n({phrase: "Bad Credentials", locale: locale})});
55 }
56
57 // Check username
5814 try {
5914 var username = utils.checkUsername(data.username);
60 } catch(e) {
615 return socket.emit("loginResult", {err: __i18n({phrase: e.message, locale: locale})});
62 }
63
649 socket.join("lobby");
659 socket.username = username;
66
679 socket.emit("loginResult", {err: null, username: username, gametypes: __staticGametypes});
68 });
69
70 /**
71 * IO : Get Rooms
72 */
731 app.io.route("getRooms", function(socket) {
742 if(!utils.isInRoom(socket, "lobby"))
751 return;
761 socket.emit("roomsList", rooms.getRooms());
77 });
78
79 /**
80 * IO : Create Room
81 */
821 app.io.route("createRoom", function(socket, data) {
836 if(!utils.isInRoom(socket, "lobby"))
841 return;
855 if(utils.isInGame(socket))
861 return;
874 rooms.createRoom(data.name, data.password, data.type, socket);
88 });
89
90 /**
91 * IO : Join Room
92 */
931 app.io.route("joinRoom", function(socket, data) {
9411 if(!utils.isInRoom(socket, "lobby"))
951 return;
9610 if(utils.isInGame(socket))
971 return;
989 rooms.joinRoom(data.id, data.password, socket);
99 });
100
101 /**
102 * IO : Leave Room
103 */
1041 app.io.route("leaveRoom", function(socket) {
1059 rooms.leaveRoom(socket);
106 });
107
108 /**
109 * IO : Kick Player
110 */
1111 app.io.route("kickPlayer", function(socket, username) {
112
1130 var room = utils.isInGame(socket);
1140 var player;
1150 if( !room
116 || room.started
117 || room.players[0] !== socket
118 || !(player = room.resolveUsername(username))) {
1190 return;
120 }
1210 room.message(username + " has been kicked out of this room.");
1220 rooms.leaveRoom(player);
123 });
124
125 /**
126 * IO : Room Parameters
127 */
1281 app.io.route("setRoomSize", function(socket, data) {
1294 var room = utils.isInGame(socket);
1304 if(room && room.players[0] === socket && room.players.length <= +data)
1313 room.setSize(+data);
132 });
133
1341 app.io.route("setRoomParameter", function(socket, data) {
1354 var room = utils.isInGame(socket);
1364 if(room && room.players[0] === socket)
1373 room.setParameter(data.parameter, data.value, socket);
138 });
139
140 /**
141 * IO : Chat Management
142 */
1431 app.io.route("sendMessage", function(socket, data) {
14427 var room = utils.isInGame(socket);
14527 var message = utils.sanitizeHtml(data.message);
14627 if(!message)
1473 return;
14824 if(room)
14924 room.sendMessage(data.channel, message, socket);
150 });
151
152 /**
153 * IO : Start Game !
154 */
1551 app.io.route("startRoom", function(socket) {
1563 var room = utils.isInGame(socket);
1573 if(room && room.players[0] === socket && !room.started && room.size === room.players.length)
1582 room.start();
159 });
160
161 /**
162 * IO : Execute Action
163 */
1641 app.io.route("executeAction", function(socket, data) {
165
16618 if(!socket.player || !data || !data.action)
1673 return; // Not authorized
168
16915 var actions = socket.player.getAvailableActions(false);
170
17115 if(!actions[data.action] || actions[data.action].locked)
1722 return; // Not ready for this action
173
17413 if(actions[data.action].type === "select"
175 && actions[data.action].options.safeChoices.indexOf(data.value) < 0)
1767 return; // Bad value
177
1786 if(actions[data.action].type === "select"
179 && actions[data.action].options.choices === "players") {
1801 data.value = socket.player.room.resolveUsername(data.value).player;
181 }
182
1836 actions[data.action].locked = true;
1846 actions[data.action].execute(socket.player, data.value);
1856 actions[data.action].locked = false;
186 });
187}
188

/home/lesterpig/workspace/openparty/lib/utils.js

100%
33
33
0
LineHitsSource
11var crypto = require("crypto");
2
31global.GET_RANDOM = function(from, to) {
41027 return Math.floor(Math.random() * (to - from + 1)) + from;
5};
6
71module.exports = {
8
9 randomString: function(len) {
103 return crypto.randomBytes(Math.ceil(len * 3 / 4))
11 .toString('base64') // convert to base64 format
12 .slice(0, len) // return required number of characters
13 .replace(/\+/g, '0') // replace '+' with '0'
14 .replace(/\//g, '0'); // replace '/' with '0'
15 },
16
17 isInRoom: function(socket, room) {
1819 return socket.rooms.indexOf(room) >= 0;
19 },
20
21 isInGame: function(socket) {
22
2357 if(!socket.currentRoom)
2414 return false;
25 else
2643 return socket.currentRoom;
27
28 },
29
30 sanitizeHtml: function(string) {
3140 if(!string)
323 return "";
3337 string = string.replace(/</ig,"<");
3437 string = string.replace(/>/ig,">");
3537 return string;
36 },
37
38 checkUsername: function(username) {
3914 if(username.length > 20)
401 throw new Error("Username is too long.");
41
4213 username = this.sanitizeHtml(username);
4313 username = username.trim();
44
4513 if(username.length === 0)
461 throw new Error("Username is invalid.");
47
48 // already connected ?
49
5012 var exists = __app.io.sockets.sockets.some(function(s) {
5163 if(!s.username)
5239 return false;
5324 if(s.username.toLowerCase() === username.toLowerCase())
543 return true;
55 });
56
5712 if(exists)
583 throw new Error("Username is not available.");
59
609 return username;
61
62 },
63
64 /** TYPES */
65
66 isString: function(s) {
6778 return typeof s === 'string' || s instanceof String;
68 },
69
70 isFunction: function(f) {
7123 return typeof f === 'function'
72 },
73
74 isInteger: function(i) {
7516 return i === parseInt(i, 10);
76 },
77
78 isArray: function(a) {
796 return require("util").isArray(a);
80 },
81
82 isObject: function(o) {
834 return typeof o === 'object'
84 }
85}
86