From 6b472dc134653c7943fa663cd69a9e29b9c48a69 Mon Sep 17 00:00:00 2001 From: logsol Date: Tue, 3 Mar 2015 23:43:15 +0100 Subject: [PATCH] added max user and refactored coordinator/serveruser a bit fixes #105 --- app/Game/Client/Networker.js | 3 +- app/Game/Config/Settings.js | 1 + app/Menu/Menu.js | 76 +++++++++++++++++++++++++----------- app/Server/Api.js | 9 +++-- app/Server/Coordinator.js | 37 ++++++------------ app/Server/PipeToChannel.js | 28 ++++++++++++- app/Server/User.js | 38 +++++++++++++----- static/css/screen.css | 29 +++++++++++++- static/html/index.html | 1 + 9 files changed, 156 insertions(+), 66 deletions(-) diff --git a/app/Game/Client/Networker.js b/app/Game/Client/Networker.js index 3b3ba12..b40477b 100755 --- a/app/Game/Client/Networker.js +++ b/app/Game/Client/Networker.js @@ -53,6 +53,7 @@ function (ProtocolHelper, GameController, User, Nc, Settings, DomController) { this.sendCommand('join', options); DomController.setConnected(true); } else { + alert("Error: no channel name"); window.location.href = "/"; } } @@ -80,7 +81,7 @@ function (ProtocolHelper, GameController, User, Nc, Settings, DomController) { } Networker.prototype.onJoinError = function(options) { - // alert(options.message); + alert(options.message); window.location.href = "/"; }; diff --git a/app/Game/Config/Settings.js b/app/Game/Config/Settings.js index 747e8c2..5fd574b 100755 --- a/app/Game/Config/Settings.js +++ b/app/Game/Config/Settings.js @@ -76,6 +76,7 @@ define(function() { NETWORK_LOG_FILTER: ['ping', 'pong', 'worldUpdate', 'lookAt'], // CHANNEL + CHANNEL_MAX_USERS: 20, CHANNEL_DESTRUCTION_TIME: 5 * 60, CHANNEL_END_ROUND_TIME: 4, //10, CHANNEL_DEFAULT_MAX_USERS: 40, diff --git a/app/Menu/Menu.js b/app/Menu/Menu.js index e0c573a..5948d7f 100644 --- a/app/Menu/Menu.js +++ b/app/Menu/Menu.js @@ -144,11 +144,19 @@ function (ColorConverter, Exception, PointerLockManager, Qs) { var html = ""; if(list.length > 0) { for (var i = 0; i < list.length; i++) { + var channel = list[i]; - html += ""; - html += "" + channel.name + ""; + var fullState = channel.playerCount >= channel.maxUsers; + var fullString = fullState ? " Full" : ""; + var fullStyle = fullState ? 'class="full"' : ""; + var players = channel.playerCount + ? "Player:
- " + channel.players.join("
- ") + "
" + : ""; + + html += ""; + html += "" + channel.channelName + ""; html += "death match"; - html += "" + channel.playerCount + ""; + html += "" + channel.playerCount + fullString + players + ""; html += ""; }; } else { @@ -190,8 +198,15 @@ function (ColorConverter, Exception, PointerLockManager, Qs) { Qs.$("form#createform").onsubmit = function(e) { try { - var channelName = Qs.$("#customname").value; - create(channelName, onCreateSuccess); + + var options = { + channelName: Qs.$("#customname").value, + levelUids: getSelectedMaps(), + maxUsers: parseInt(Qs.$("#userLimit").value, 10), + scoreLimit: parseInt(Qs.$("#scoreLimit").value, 10) + }; + + create(options, onCreateSuccess); } catch(e) { console.error(e) } @@ -246,7 +261,15 @@ function (ColorConverter, Exception, PointerLockManager, Qs) { } if(!channelExists(list, defaultChannelName)) { - create(defaultChannelName, function() { + + var options = { + channelName: defaultChannelName, + levelUids: getSelectedMaps(), + maxUsers: parseInt(Qs.$("#userLimit").value, 10), + scoreLimit: parseInt(Qs.$("#scoreLimit").value, 10) + }; + + create(options, function() { join(nickname, defaultChannelName); // only called on success }); } else { @@ -283,7 +306,7 @@ function (ColorConverter, Exception, PointerLockManager, Qs) { function channelExists(list, channelName) { for (var i = 0; i < list.length; i++) { var channel = list[i]; - if(channel.name == channelName) { + if(channel.channelName == channelName) { return true; } } @@ -302,18 +325,33 @@ function (ColorConverter, Exception, PointerLockManager, Qs) { return true; } - function validateForCreate(channelName, maps) { + function validateForCreate(options) { + return true; - if(maps.length < 1) { + // great validation on server side does it all. + + /* + if(options.levelUids.length < 1) { alert("Please choose at least one map.") return false; } - if(!channelName) { - alert("Please provide a channel name.") + if(!options.channelName || options.channelName.length < 3) { + alert("Please provide a channel name of at least 3 characters.") + return false; + } + + if(!parseInt(options.maxUsers) > 1 || !parseInt(options.maxUsers) < 20) { + alert("Number of users must be larger than 1 and smaller than 20."); + return false; + } + + if(!parseInt(options.scoreLimit) > 1 || !parseInt(options.scoreLimit) < 99) { + alert("Score limit must be larger than 1 and smaller than 99."); return false; } return true; + */ } function getSelectedMaps() { @@ -367,20 +405,12 @@ function (ColorConverter, Exception, PointerLockManager, Qs) { } } - function create(channelName, callback) { - var maps = getSelectedMaps(); + function create(options, callback) { - if(validateForCreate(channelName, maps)) { + if(validateForCreate(options)) { - var options = { - channelName: channelName, - levelUids: maps, - maxUsers: 10, - minUsers: 2, - scoreLimit: parseInt(Qs.$("#scoreLimit").value, 10) - } - - localStorage["customname"] = channelName; + options["minUsers"] = 1; + localStorage["customname"] = options.channelName; ajax("createChannel", options, function(responseText) { if(typeof callback == 'function') { diff --git a/app/Server/Api.js b/app/Server/Api.js index 5eb5cc6..47b4a63 100644 --- a/app/Server/Api.js +++ b/app/Server/Api.js @@ -96,22 +96,23 @@ function (Nc, ProtocolHelper, validate, Options, Settings, FileSystem) { newOptions.maxUsers = options.maxUsers; } else { this.isError = true; - return "Could not create channel, Max users invalid. (Limited to " + Settings.CHANNEL_MAX_USERS + " users)"; + return "Could not create channel, user limit invalid. Limited to " + Settings.CHANNEL_MAX_USERS + " users"; } if(validate(options.minUsers, {optional: true, type: 'number', min: 0, max: Settings.CHANNEL_MAX_USERS})) { newOptions.minUsers = options.minUsers; } else { this.isError = true; - return "Could not create channel, Max users too high. Limited to: " + Settings.CHANNEL_MAX_USERS; + return "Could not create channel, minimal users limit too high. Limited to: " + Settings.CHANNEL_MAX_USERS; } // Limits - if(validate(options.scoreLimit, {type: 'number', min: 1, max: 999})) { + var scoreLimitPreferences = {type: 'number', min: 1, max: 999}; + if(validate(options.scoreLimit, scoreLimitPreferences)) { newOptions.scoreLimit = options.scoreLimit; } else { this.isError = true; - return "Could not create channel, score limit (" + options.scoreLimit + ")."; + return "Could not create channel, score limit (" + options.scoreLimit + ") must be between " + scoreLimitPreferences.min + " and " + scoreLimitPreferences.max; } var defaultOptions = { diff --git a/app/Server/Coordinator.js b/app/Server/Coordinator.js index a5da29c..2e2060d 100644 --- a/app/Server/Coordinator.js +++ b/app/Server/Coordinator.js @@ -11,7 +11,6 @@ function (User, PipeToChannel, Nc, Settings) { function Coordinator() { this.channelPipes = {}; - this.users = []; Nc.on(Nc.ns.server.events.controlCommand.coordinator, this.onMessage, this); @@ -19,21 +18,12 @@ function (User, PipeToChannel, Nc, Settings) { } Coordinator.prototype.createUser = function (socketLink) { - this.users.push(new User(socketLink, this)); + new User(socketLink, this); } - Coordinator.prototype.removeUser = function (user) { - for(var i = 0; i < this.users.length; i++) { - if(this.users[i] === user) { - this.users.splice(i, 1); - break; - } - } - } - - Coordinator.prototype.assignUserToChannel = function (user, channelName) { - var channelPipe = this.channelPipes[channelName]; - user.setChannelPipe(channelPipe); + // was assignUserToChannel... + Coordinator.prototype.getChannelPipeByName = function (channelName) { + return this.channelPipes[channelName]; } Coordinator.prototype.onDestroyPipe = function(channelName) { @@ -44,18 +34,17 @@ function (User, PipeToChannel, Nc, Settings) { var list = []; for (var channelName in this.channelPipes) { - var count = 0; + var options = this.channelPipes[channelName].options; - for(var i = 0; i < this.users.length; i++) { - if(this.users[i].channelPipe === this.channelPipes[channelName]){ - count++; - } - } + var playerNames = []; + var users = this.channelPipes[channelName].getUsers(); + for (var i = 0; i < users.length; i++) { + playerNames[i] = users[i].options.nickname; + }; + options.players = playerNames; + options.playerCount = options.players.length; - list.push({ - name: channelName, - playerCount: count - }); + list.push(options); } return list; } diff --git a/app/Server/PipeToChannel.js b/app/Server/PipeToChannel.js index 0e4ff97..7112783 100755 --- a/app/Server/PipeToChannel.js +++ b/app/Server/PipeToChannel.js @@ -12,6 +12,8 @@ function (Nc, childProcess) { function PipeToChannel (options) { this.fork = null; + this.options = options; + this.users = []; try { this.fork = fork('channel.js' @@ -28,8 +30,6 @@ function (Nc, childProcess) { this.send('channel/' + options.channelName, { CREATE: true, options: options }); this.fork.on('message', this.onMessage.bind(this)); - - var self = this; } // While creating user @@ -52,6 +52,10 @@ function (Nc, childProcess) { this.fork.send(message); } + PipeToChannel.prototype.isFull = function() { + return this.users.length >= this.options.maxUsers; + }; + PipeToChannel.prototype.onMessage = function (message) { switch(message.recipient) { case 'coordinator': @@ -64,6 +68,26 @@ function (Nc, childProcess) { } + PipeToChannel.prototype.addUser = function(user) { + this.users.push(user); + this.send('channel', { addUser: user.options }); + }; + + PipeToChannel.prototype.removeUser = function(user) { + for(var i = 0; i < this.users.length; i++) { + if(this.users[i] === user) { + this.users.splice(i, 1); + break; + } + } + + this.send('channel', { releaseUser: user.id }); + }; + + PipeToChannel.prototype.getUsers = function() { + return this.users; + }; + return PipeToChannel; }); \ No newline at end of file diff --git a/app/Server/User.js b/app/Server/User.js index 44194a0..a9d63a2 100644 --- a/app/Server/User.js +++ b/app/Server/User.js @@ -14,6 +14,7 @@ function (Parent, ProtocolHelper, Nc) { this.coordinator = coordinator; this.socketLink = socketLink; this.channelPipe = null; + this.options = null; socketLink.on('message', this.onMessage.bind(this)); socketLink.on('disconnect', this.onDisconnect.bind(this)); @@ -23,15 +24,23 @@ function (Parent, ProtocolHelper, Nc) { User.prototype = Object.create(Parent.prototype); +/* User.prototype.setChannelPipe = function(channelPipe) { if(channelPipe) { - this.channelPipe = channelPipe; + if (channelPipe.isWithinUserLimit()) { + this.channelPipe = channelPipe; + this.channelPipe.addUser(this); + } else { + var message = ProtocolHelper.encodeCommand("joinError", {message:"Channel is full"}); + this.socketLink.send(message); + } + } else { var message = ProtocolHelper.encodeCommand("joinError", {message:"Channel not found"}); this.socketLink.send(message); } }; - + */ // Socket callbacks @@ -41,14 +50,12 @@ function (Parent, ProtocolHelper, Nc) { User.prototype.onDisconnect = function () { - this.coordinator.removeUser(this); - if(!this.channelPipe) { - console.warn("Disconnecting user without a channel."); + console.warn("Disconnecting user without a channel. (Maybe channel was full)"); return; } - this.channelPipe.send('channel', { releaseUser: this.id }); + this.channelPipe.removeUser(this); } @@ -56,18 +63,29 @@ function (Parent, ProtocolHelper, Nc) { // Remember: control commands are coordinator relevant commands User.prototype.onJoin = function(options) { - this.coordinator.assignUserToChannel(this, options.channelName); - if(!this.channelPipe) { - console.warn("Can not join user because channel (" + options.channelName + ") does not exist.") + var channelPipe = this.coordinator.getChannelPipeByName(options.channelName); + + if(!channelPipe) { + var message = ProtocolHelper.encodeCommand("joinError", {message:"Channel " + options.channelName + " not found."}); + this.socketLink.send(message); return; } + if (channelPipe.isFull()) { + var message = ProtocolHelper.encodeCommand("joinError", {message:"Sorry! Channel " + options.channelName + " is full."}); + this.socketLink.send(message); + return; + } + + this.channelPipe = channelPipe; + var userOptions = { id: this.id, nickname: options.nickname } - this.channelPipe.send('channel', { addUser: userOptions }); + this.options = userOptions; + this.channelPipe.addUser(this); }; /* FIXME: watch out and check in wich direction game and control commands flow */ diff --git a/static/css/screen.css b/static/css/screen.css index 83213d4..6cc74a3 100644 --- a/static/css/screen.css +++ b/static/css/screen.css @@ -20,7 +20,7 @@ body { background: #222; color: #ccc; font-family: 'Joystix', "Lucida Grande", sans-serif; - text-transform: uppercase; + /*text-transform: uppercase;*/ margin: 0; padding: 0; display: table; @@ -113,7 +113,7 @@ article#menu { margin: 4em auto; background: #1a1a1a; padding: 2em; - max-width: 30em; + max-width: 40em; } table, th, td { @@ -142,6 +142,31 @@ tr:hover td { background: #222; } +.full { + color: #777; +} + +.full a { + color: inherit; + cursor:not-allowed;; +} + +#players { + position: absolute; + + border: 1px solid #777; + padding: 20px; + margin-left: 35px; + margin-top: -10px; + background: rgba(20, 20, 20, 0.95); + box-shadow: 5px 5px 5px #000; + display: none; +} + +.playersCell:hover #players { + display: block; +} + a { color: #ccc; } diff --git a/static/html/index.html b/static/html/index.html index 37dd78b..fb062a7 100644 --- a/static/html/index.html +++ b/static/html/index.html @@ -22,6 +22,7 @@

Create your own!

+

Maps