mirror of
https://github.com/logsol/chuck.js.git
synced 2026-05-11 10:37:34 +00:00
added max user and refactored coordinator/serveruser a bit fixes #105
This commit is contained in:
parent
ccd146f01b
commit
6b472dc134
9 changed files with 156 additions and 66 deletions
|
|
@ -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 = "/";
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 += "<tr>";
|
||||
html += "<td><a href='#" + channel.name + "'>" + channel.name + "</a></td>";
|
||||
var fullState = channel.playerCount >= channel.maxUsers;
|
||||
var fullString = fullState ? " Full" : "";
|
||||
var fullStyle = fullState ? 'class="full"' : "";
|
||||
var players = channel.playerCount
|
||||
? "<span id='players'>Player:<br>- " + channel.players.join("<br>- ") + "</span>"
|
||||
: "";
|
||||
|
||||
html += "<tr "+fullStyle+">";
|
||||
html += "<td><a href='#" + channel.channelName + "'>" + channel.channelName + "</a></td>";
|
||||
html += "<td>death match</td>";
|
||||
html += "<td>" + channel.playerCount + "</td>";
|
||||
html += "<td class='playersCell'>" + channel.playerCount + fullString + players + "</td>";
|
||||
html += "</tr>";
|
||||
};
|
||||
} 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') {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
});
|
||||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
<h2>Create your own!</h2>
|
||||
<p><label>Name:<br> <input id="customname"></label></p>
|
||||
<p><label>Score limit:<br> <input id="scoreLimit" type="number" value="5"></label></p>
|
||||
<p><label>User limit:<br> <input id="userLimit" type="number" value="10"></label></p>
|
||||
<fieldset>
|
||||
<legend>Maps</legend>
|
||||
<ul id="maps">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue