casino-server
Version:
An multi-rule scalable online poker game server powered by redis, node.js and socket.io
413 lines (344 loc) • 7.9 kB
JavaScript
var Gamer = require('./gamer');
exports = module.exports = Room;
function Room( casino, typeid, roomid, options ) {
this.options = {
max_seats: 4
};
if(options && (typeof options === 'object')) {
for(var i in options) this.options[i] = options[i];
}
this.casino = casino;
this.db = casino.db;
this.pub = casino.pub;
this.id = roomid;
this.type = typeid;
this.name = '';
this.gamers = {};
this.gamers_count = 0;
this.seats_count = this.options.max_seats;
this.seats_taken = 0;
this.seats = [];
for(var j=0; j<this.seats_count; j++) {
this.seats.push(null);
}
var room = this;
this.timer = setInterval(function(){
room.tick();
}, 1000);
}
Room.prototype.setName = function(name) {
this.name = name;
};
Room.prototype.brief = function(){
return {
id: this.id,
type: this.type,
name: this.name,
casino: this.casino.id,
seats_count: this.seats_count,
seats_taken: this.seats_taken,
gamers_count: this.gamers_count
};
};
Room.prototype.details = function(){
var gamers = this.gamers;
var data = {};
for(var i in gamers) {
data[i] = gamers[i].getProfile();
}
return {
id: this.id,
type: this.type,
name: this.name,
casino: this.casino.id,
options: this.options,
seats_count: this.seats_count,
seats_taken: this.seats_taken,
gamers_count: this.gamers_count,
gamers: data,
seats: this.seats
};
};
Room.prototype.tick = function() {
};
Room.prototype.close = function() {
this.notifyAll('roomclose', 0);
this.gamers = {};
this.gamers_count = 0;
var seats = this.seats;
for(var i=0, len=seats.length; i<len; i++) {
seats[i] = null;
}
this.seats_taken = 0;
};
Room.prototype.onMessage = function(message) {
//console.log(this.id, message, typeof message);
try {
var req = JSON.parse(message);
if(req && (typeof req === 'object')) {
var room = this;
var uid = req.uid;
if(uid) {
var method = room[ 'onGamer_' + req.f ];
if(typeof method === 'function') {
method.call(room, req, function(err,ret){
room.response(req, err, ret);
});
} else {
room.response(req, 404, 'method ' + req.f + ' not supported');
}
}
}
} catch( err ) {
console.log(err);
}
};
Room.prototype.response = function(req, err, ret) {
var pub = this.pub;
pub.publish('user:#' + req.uid, JSON.stringify({
f: 'response',
seq: req.seq,
err: err,
ret: ret
}));
};
Room.prototype.notify = function(uid, event, args) {
this.pub.publish('user:#'+uid, JSON.stringify({
f:'event',
uid: uid,
e: event,
args: args
}));
};
Room.prototype.notifyAll = function(event, args) {
var pub = this.pub;
var gamers = this.gamers;
for(var i in gamers) {
var uid = gamers[i].uid;
pub.publish('user:#'+uid, JSON.stringify({
f:'event',
uid: uid,
e: event,
args: args
}));
}
};
Room.prototype.notifyAllExcept = function(ex_uid, event, args) {
var pub = this.pub;
var gamers = this.gamers;
for(var i in gamers) {
var uid = gamers[i].uid;
if(uid === ex_uid) continue;
pub.publish('user:#'+uid, JSON.stringify({
f:'event',
uid: uid,
e: event,
args: args
}));
}
};
Room.prototype.onGamer_relogin = function(req, reply) {
var room = this;
var uid = req.uid;
var gamer = room.gamers[uid];
if(gamer) {
room.notifyAll('relogin', {
uid: req.uid,
where: room.id
});
room.notify(uid, 'look', room.details());
room.notify(req.uid, 'prompt', {
leave: true,
say: 'text',
takeseat: ((gamer.seat>=0) ? null : true),
unseat: ((gamer.seat>=0) ? true : null)
});
reply(0, {});
} else {
reply(404, 'not found');
}
};
Room.prototype.onGamer_refresh = function(req, reply) {
var room = this;
var uid = req.uid;
var gamer = room.gamers[uid];
if(gamer) {
var db = room.db;
db.hgetall('user:#'+uid, function(err,ret){
if(err) { reply(500, 'db err'); return; }
if(! ret) { reply(404, 'user ' + uid + ' not found'); return; }
gamer.setProfile(ret);
room.notifyAll('refresh', {
uid: uid,
profile: gamer.getProfile()
});
reply(0, {});
});
} else {
reply(404, 'not found');
}
};
Room.prototype.onGamer_drop = function(req, reply) {
var room = this;
room.notifyAll('drop', {
uid: req.uid,
where: room.id
});
reply(0, {});
};
Room.prototype.onGamer_enter = function(req, reply) {
var room = this;
var uid = req.uid;
var gamers = this.gamers;
if(uid in gamers) {
reply(400, 'already in room');
return;
}
var db = this.db;
db.hgetall('user:#'+uid, function(err,ret){
if(err) { reply(500, 'db err'); return; }
if(! ret) { reply(404, 'user ' + uid + ' not found'); return; }
var gamer = new Gamer().setProfile(ret);
gamer.room = room;
gamer.seat = -1;
room.gamers[ uid ] = gamer;
room.gamers_count ++;
if(room.gamers_count >= room.seats_count) {
db.zrem('game:#' + room.type + '#rooms_notfull', room.id);
}
room.notify(uid, 'look', room.details());
room.notifyAll('enter', {
who: gamer.getProfile(),
where: room.id
});
var cmds = {
enter: null,
entergame: null,
leave: true,
say: 'text',
takeseat: true
};
req.args = '';
room.onGamer_takeseat(req, function(e,r){
if((! e) && r.cmds) {
for(var i in r.cmds) cmds[i] = r.cmds[i];
}
});
reply(0, {
cmds: cmds
});
room.pub.publish('user:log', 'gamer (' + uid + ') enter room #' + room.id );
});
};
Room.prototype.onGamer_leave = function(req, reply) {
var room = this;
var uid = req.uid;
var gamers = this.gamers;
if(!(uid in gamers)) return;
var cmds = {};
var gamer = gamers[ uid ];
if(gamer.seat >= 0) {
room.onGamer_unseat(req, function(e,r){
if((! e) && r.cmds) cmds = r.cmds;
});
}
room.notifyAll('leave', {
uid: uid,
where: room.id
});
delete room.gamers[uid];
room.gamers_count --;
if(room.gamers_count < room.seats_count) {
var now = Date.now();
room.db.zadd('game:#' + room.type + '#rooms_notfull', now, room.id);
}
var leavecmds = {
leave: null,
say: null,
takeseat: null,
unseat: null
};
for(var i in leavecmds) cmds[i] = leavecmds[i];
reply(0, {
cmds: cmds
});
room.pub.publish('user:log', 'gamer (' + uid + ') leave room #' + room.id );
};
Room.prototype.onGamer_look = function(req, reply) {
room.notify(req.uid, 'look', this.details());
reply(0, {});
};
Room.prototype.onGamer_say = function(req, reply) {
var room = this;
room.notifyAll('say', {
uid: req.uid,
msg: req.args
});
reply(0, {});
};
Room.prototype.onGamer_takeseat = function(req, reply) {
var room = this;
var uid = req.uid;
var gamers = this.gamers;
var gamer = gamers[ uid ];
if(gamer.seat >= 0) {
reply(400, 'already seated at ' + gamer.seat);
return false;
}
var seat = req.args, seats = room.seats;
if((typeof seat !== 'string') || (seat.length === 0)) {
for(var i=0, len=seats.length; i<len; i++) {
if(seats[i] === null) {
seat = i;
break;
}
}
}
var seatid = parseInt(seat);
if(seatid >=0 && seatid < this.seats_count) {
var seated = this.seats[seatid];
if( seated === null) {
this.seats[seatid] = uid;
gamer.seat = seatid;
this.seats_taken ++;
room.notifyAll('takeseat', {
uid: uid,
where: seatid
});
reply(0, {
cmds: {
unseat: true,
takeseat: null
}
});
} else {
reply(403, 'seat ' + seatid + ' already taken by ' + seated);
}
} else {
reply(400, 'invalid seat');
}
};
Room.prototype.onGamer_unseat = function(req, reply) {
var room = this;
var uid = req.uid;
var gamers = this.gamers;
var gamer = gamers[ uid ];
if(gamer.seat < 0) {
reply(400, 'not in seat');
return false;
}
var seatid = gamer.seat;
this.seats[seatid] = null;
this.seats_taken --;
gamer.seat = -1;
room.notifyAll('unseat', {
uid: uid,
where: seatid
});
reply(0, {
cmds: {
unseat: null,
takeseat: true
}
});
};