cc.Class({
extends: cc.Component,
properties: {
dataEventHandler:null,
roomId:null,
maxNumOfGames:0,
numOfGames:0,
numOfMJ:0,
seatIndex:-1,
seats:null,
turn:-1,
button:-1,
dingque:-1,
chupai:-1,
isDingQueing:false,
isHuanSanZhang:false,
gamestate:"",
isOver:false,
dissoveData:null,
// foo: {
// default: null,
// url: cc.Texture2D, // optional, default is typeof default
// serializable: true, // optional, default is true
// visible: true, // optional, default is true
// displayName: 'Foo', // optional
// readonly: false, // optional, default is false
// },
// ...
},
reset:function(){
this.turn = -1;
this.chupai = -1,
this.dingque = -1;
this.button = -1;
this.gamestate = "";
this.dingque = -1;
this.isDingQueing = false;
this.isHuanSanZhang = false;
this.curaction = null;
for(var i = 0; i < this.seats.length; ++i){
this.seats[i].holds = [];
this.seats[i].folds = [];
this.seats[i].pengs = [];
this.seats[i].angangs = [];
this.seats[i].diangangs = [];
this.seats[i].wangangs = [];
this.seats[i].dingque = -1;
this.seats[i].ready = false;
this.seats[i].hued = false;
this.seats[i].huanpais = null;
this.huanpaimethod = -1;
}
},
clear:function(){
this.dataEventHandler = null;
if(this.isOver == null){
this.seats = null;
this.roomId = null;
this.maxNumOfGames = 0;
this.numOfGames = 0;
}
},
dispatchEvent(event,data){
if(this.dataEventHandler){
this.dataEventHandler.emit(event,data);
}
},
getSeatIndexByID:function(userId){
for(var i = 0; i < this.seats.length; ++i){
var s = this.seats[i];
if(s.userid == userId){
return i;
}
}
return -1;
},
isOwner:function(){
return this.seatIndex == 0;
},
getSeatByID:function(userId){
var seatIndex = this.getSeatIndexByID(userId);
var seat = this.seats[seatIndex];
return seat;
},
getSelfData:function(){
return this.seats[this.seatIndex];
},
getLocalIndex:function(index){
var ret = (index - this.seatIndex + 4) % 4;
return ret;
},
prepareReplay:function(roomInfo,detailOfGame){
this.roomId = roomInfo.id;
this.seats = roomInfo.seats;
this.turn = detailOfGame.base_info.button;
var baseInfo = detailOfGame.base_info;
for(var i = 0; i < this.seats.length; ++i){
var s = this.seats[i];
s.seatindex = i;
s.score = null;
s.holds = baseInfo.game_seats[i];
s.pengs = [];
s.angangs = [];
s.diangangs = [];
s.wangangs = [];
s.folds = [];
console.log(s);
if(cc.vv.userMgr.userId == s.userid){
this.seatIndex = i;
}
}
this.conf = {
type:baseInfo.type,
}
if(this.conf.type == null){
this.conf.type == "xzdd";
}
},
getWanfa:function(){
var conf = this.conf;
if(conf && conf.maxGames!=null && conf.maxFan!=null){
var strArr = [];
strArr.push(conf.maxGames + "局");
strArr.push(conf.maxFan + "番封顶");
if(conf.hsz){
strArr.push("换三张");
}
if(conf.zimo == 1){
strArr.push("自摸加番");
}
else{
strArr.push("自摸加底");
}
if(conf.jiangdui){
strArr.push("将对");
}
if(conf.dianganghua == 1){
strArr.push("点杠花(自摸)");
}
else{
strArr.push("点杠花(放炮)");
}
if(conf.menqing){
strArr.push("门清、中张");
}
if(conf.tiandihu){
strArr.push("天地胡");
}
return strArr.join(" ");
}
return "";
},
initHandlers:function(){
var self = this;
cc.vv.net.addHandler("login_result",function(data){
console.log(data);
if(data.errcode === 0){
var data = data.data;
self.roomId = data.roomid;
self.conf = data.conf;
self.maxNumOfGames = data.conf.maxGames;
self.numOfGames = data.numofgames;
self.seats = data.seats;
self.seatIndex = self.getSeatIndexByID(cc.vv.userMgr.userId);
self.isOver = false;
}
else{
console.log(data.errmsg);
}
self.dispatchEvent('login_result');
});
cc.vv.net.addHandler("login_finished",function(data){
console.log("login_finished");
cc.director.loadScene("mjgame",function(){
cc.vv.net.ping();
cc.vv.wc.hide();
});
self.dispatchEvent("login_finished");
});
cc.vv.net.addHandler("exit_result",function(data){
self.roomId = null;
self.turn = -1;
self.dingque = -1;
self.isDingQueing = false;
self.seats = null;
});
cc.vv.net.addHandler("exit_notify_push",function(data){
var userId = data;
var s = self.getSeatByID(userId);
if(s != null){
s.userid = 0;
s.name = "";
self.dispatchEvent("user_state_changed",s);
}
});
cc.vv.net.addHandler("dispress_push",function(data){
self.roomId = null;
self.turn = -1;
self.dingque = -1;
self.isDingQueing = false;
self.seats = null;
});
cc.vv.net.addHandler("disconnect",function(data){
if(self.roomId == null){
cc.vv.wc.show('正在返回游戏大厅');
cc.director.loadScene("hall");
}
else{
if(self.isOver == false){
cc.vv.userMgr.oldRoomId = self.roomId;
self.dispatchEvent("disconnect");
}
else{
self.roomId = null;
}
}
});
cc.vv.net.addHandler("new_user_comes_push",function(data){
//console.log(data);
var seatIndex = data.seatindex;
var needCheckIp = false;
if(self.seats[seatIndex].userid > 0){
self.seats[seatIndex].online = true;
if(self.seats[seatIndex].ip != data.ip){
self.seats[seatIndex].ip = data.ip;
needCheckIp = true;
}
}
else{
data.online = true;
self.seats[seatIndex] = data;
needCheckIp = true;
}
self.dispatchEvent('new_user',self.seats[seatIndex]);
if(needCheckIp){
self.dispatchEvent('check_ip',self.seats[seatIndex]);
}
});
cc.vv.net.addHandler("user_state_push",function(data){
//console.log(data);
var userId = data.userid;
var seat = self.getSeatByID(userId);
seat.online = data.online;
self.dispatchEvent('user_state_changed',seat);
});
cc.vv.net.addHandler("user_ready_push",function(data){
//console.log(data);
var userId = data.userid;
var seat = self.getSeatByID(userId);
seat.ready = data.ready;
self.dispatchEvent('user_state_changed',seat);
});
cc.vv.net.addHandler("game_holds_push",function(data){
var seat = self.seats[self.seatIndex];
console.log(data);
seat.holds = data;
for(var i = 0; i < self.seats.length; ++i){
var s = self.seats[i];
if(s.folds == null){
s.folds = [];
}
if(s.pengs == null){
s.pengs = [];
}
if(s.angangs == null){
s.angangs = [];
}
if(s.diangangs == null){
s.diangangs = [];
}
if(s.wangangs == null){
s.wangangs = [];
}
s.ready = false;
}
self.dispatchEvent('game_holds');
});
cc.vv.net.addHandler("game_begin_push",function(data){
console.log('game_action_push');
console.log(data);
self.button = data;
self.turn = self.button;
self.gamestate = "begin";
self.dispatchEvent('game_begin');
});
cc.vv.net.addHandler("game_playing_push",function(data){
console.log('game_playing_push');
self.gamestate = "playing";
self.dispatchEvent('game_playing');
});
cc.vv.net.addHandler("game_sync_push",function(data){
console.log("game_sync_push");
console.log(data);
self.numOfMJ = data.numofmj;
self.gamestate = data.state;
if(self.gamestate == "dingque"){
self.isDingQueing = true;
}
else if(self.gamestate == "huanpai"){
self.isHuanSanZhang = true;
}
self.turn = data.turn;
self.button = data.button;
self.chupai = data.chuPai;
self.huanpaimethod = data.huanpaimethod;
for(var i = 0; i < 4; ++i){
var seat = self.seats[i];
var sd = data.seats[i];
seat.holds = sd.holds;
seat.folds = sd.folds;
seat.angangs = sd.angangs;
seat.diangangs = sd.diangangs;
seat.wangangs = sd.wangangs;
seat.pengs = sd.pengs;
seat.dingque = sd.que;
seat.hued = sd.hued;
seat.iszimo = sd.iszimo;
seat.huinfo = sd.huinfo;
seat.huanpais = sd.huanpais;
if(i == self.seatIndex){
self.dingque = sd.que;
}
}
self.dispatchEvent('game_sync');
});
cc.vv.net.addHandler("game_dingque_push",function(data){
self.isDingQueing = true;
self.isHuanSanZhang = false;
self.gamestate = 'dingque';
self.dispatchEvent('game_dingque');
});
cc.vv.net.addHandler("game_huanpai_push",function(data){
self.isHuanSanZhang = true;
self.dispatchEvent('game_huanpai');
});
cc.vv.net.addHandler("hangang_notify_push",function(data){
self.dispatchEvent('hangang_notify',data);
});
cc.vv.net.addHandler("game_action_push",function(data){
self.curaction = data;
console.log(data);
self.dispatchEvent('game_action',data);
});
cc.vv.net.addHandler("game_chupai_push",function(data){
console.log('game_chupai_push');
//console.log(data);
var turnUserID = data;
var si = self.getSeatIndexByID(turnUserID);
self.doTurnChange(si);
});
cc.vv.net.addHandler("game_num_push",function(data){
self.numOfGames = data;
self.dispatchEvent('game_num',data);
});
cc.vv.net.addHandler("game_over_push",function(data){
console.log('game_over_push');
var results = data.results;
for(var i = 0; i < self.seats.length; ++i){
self.seats[i].score = results.length == 0? 0:results[i].totalscore;
}
self.dispatchEvent('game_over',results);
if(data.endinfo){
self.isOver = true;
self.dispatchEvent('game_end',data.endinfo);
}
self.reset();
for(var i = 0; i < self.seats.length; ++i){
self.dispatchEvent('user_state_changed',self.seats[i]);
}
});
cc.vv.net.addHandler("mj_count_push",function(data){
console.log('mj_count_push');
self.numOfMJ = data;
//console.log(data);
self.dispatchEvent('mj_count',data);
});
cc.vv.net.addHandler("hu_push",function(data){
console.log('hu_push');
console.log(data);
self.doHu(data);
});
cc.vv.net.addHandler("game_chupai_notify_push",function(data){
var userId = data.userId;
var pai = data.pai;
var si = self.getSeatIndexByID(userId);
self.doChupai(si,pai);
});
cc.vv.net.addHandler("game_mopai_push",function(data){
console.log('game_mopai_push');
self.doMopai(self.seatIndex,data);
});
cc.vv.net.addHandler("guo_notify_push",function(data){
console.log('guo_notify_push');
var userId = data.userId;
var pai = data.pai;
var si = self.getSeatIndexByID(userId);
self.doGuo(si,pai);
});
cc.vv.net.addHandler("guo_result",function(data){
console.log('guo_result');
self.dispatchEvent('guo_result');
});
cc.vv.net.addHandler("guohu_push",function(data){
console.log('guohu_push');
self.dispatchEvent("push_notice",{info:"过胡",time:1.5});
});
cc.vv.net.addHandler("huanpai_notify",function(data){
var seat = self.getSeatByID(data.si);
seat.huanpais = data.huanpais;
self.dispatchEvent('huanpai_notify',seat);
});
cc.vv.net.addHandler("game_huanpai_over_push",function(data){
console.log('game_huanpai_over_push');
var info = "";
var method = data.method;
if(method == 0){
info = "换对家牌";
}
else if(method == 1){
info = "换下家牌";
}
else{
info = "换上家牌";
}
self.huanpaimethod = method;
cc.vv.gameNetMgr.isHuanSanZhang = false;
self.dispatchEvent("game_huanpai_over");
self.dispatchEvent("push_notice",{info:info,time:2});
});
cc.vv.net.addHandler("peng_notify_push",function(data){
console.log('peng_notify_push');
console.log(data);
var userId = data.userid;
var pai = data.pai;
var si = self.getSeatIndexByID(userId);
self.doPeng(si,data.pai);
});
cc.vv.net.addHandler("gang_notify_push",function(data){
console.log('gang_notify_push');
console.log(data);
var userId = data.userid;
var pai = data.pai;
var si = self.getSeatIndexByID(userId);
self.doGang(si,pai,data.gangtype);
});
cc.vv.net.addHandler("game_dingque_notify_push",function(data){
self.dispatchEvent('game_dingque_notify',data);
});
cc.vv.net.addHandler("game_dingque_finish_push",function(data){
for(var i = 0; i < data.length; ++i){
self.seats[i].dingque = data[i];
if(i == self.seatIndex){
self.dingque = data[i];
}
}
self.dispatchEvent('game_dingque_finish',data);
});
cc.vv.net.addHandler("chat_push",function(data){
self.dispatchEvent("chat_push",data);
});
cc.vv.net.addHandler("quick_chat_push",function(data){
self.dispatchEvent("quick_chat_push",data);
});
cc.vv.net.addHandler("emoji_push",function(data){
self.dispatchEvent("emoji_push",data);
});
cc.vv.net.addHandler("dissolve_notice_push",function(data){
console.log("dissolve_notice_push");
console.log(data);
self.dissoveData = data;
self.dispatchEvent("dissolve_notice",data);
});
cc.vv.net.addHandler("dissolve_cancel_push",function(data){
self.dissoveData = null;
self.dispatchEvent("dissolve_cancel",data);
});
cc.vv.net.addHandler("voice_msg_push",function(data){
self.dispatchEvent("voice_msg",data);
});
},
doGuo:function(seatIndex,pai){
var seatData = this.seats[seatIndex];
var folds = seatData.folds;
folds.push(pai);
this.dispatchEvent('guo_notify',seatData);
},
doMopai:function(seatIndex,pai){
var seatData = this.seats[seatIndex];
if(seatData.holds){
seatData.holds.push(pai);
this.dispatchEvent('game_mopai',{seatIndex:seatIndex,pai:pai});
}
},
doChupai:function(seatIndex,pai){
this.chupai = pai;
var seatData = this.seats[seatIndex];
if(seatData.holds){
var idx = seatData.holds.indexOf(pai);
seatData.holds.splice(idx,1);
}
this.dispatchEvent('game_chupai_notify',{seatData:seatData,pai:pai});
},
doPeng:function(seatIndex,pai){
var seatData = this.seats[seatIndex];
//移除手牌
if(seatData.holds){
for(var i = 0; i < 2; ++i){
var idx = seatData.holds.indexOf(pai);
seatData.holds.splice(idx,1);
}
}
//更新碰牌数据
var pengs = seatData.pengs;
pengs.push(pai);
this.dispatchEvent('peng_notify',seatData);
},
getGangType:function(seatData,pai){
if(seatData.pengs.indexOf(pai) != -1){
return "wangang";
}
else{
var cnt = 0;
for(var i = 0; i < seatData.holds.length; ++i){
if(seatData.holds[i] == pai){
cnt++;
}
}
if(cnt == 3){
return "diangang";
}
else{
return "angang";
}
}
},
doGang:function(seatIndex,pai,gangtype){
var seatData = this.seats[seatIndex];
if(!gangtype){
gangtype = this.getGangType(seatData,pai);
}
if(gangtype == "wangang"){
if(seatData.pengs.indexOf(pai) != -1){
var idx = seatData.pengs.indexOf(pai);
if(idx != -1){
seatData.pengs.splice(idx,1);
}
}
seatData.wangangs.push(pai);
}
if(seatData.holds){
for(var i = 0; i <= 4; ++i){
var idx = seatData.holds.indexOf(pai);
if(idx == -1){
//如果没有找到,表示移完了,直接跳出循环
break;
}
seatData.holds.splice(idx,1);
}
}
if(gangtype == "angang"){
seatData.angangs.push(pai);
}
else if(gangtype == "diangang"){
seatData.diangangs.push(pai);
}
this.dispatchEvent('gang_notify',{seatData:seatData,gangtype:gangtype});
},
doHu:function(data){
this.dispatchEvent('hupai',data);
},
doTurnChange:function(si){
var data = {
last:this.turn,
turn:si,
}
this.turn = si;
this.dispatchEvent('game_chupai',data);
},
connectGameServer:function(data){
this.dissoveData = null;
cc.vv.net.ip = data.ip + ":" + data.port;
console.log(cc.vv.net.ip);
var self = this;
var onConnectOK = function(){
console.log("onConnectOK");
var sd = {
token:data.token,
roomid:data.roomid,
time:data.time,
sign:data.sign,
};
cc.vv.net.send("login",sd);
};
var onConnectFailed = function(){
console.log("failed.");
cc.vv.wc.hide();
};
cc.vv.wc.show("正在进入房间");
cc.vv.net.connect(onConnectOK,onConnectFailed);
}
// called every frame, uncomment this function to activate update callback
// update: function (dt) {
// },
});
(1)连接至麻将服务器后,调用 cc.vv.gameNetMgr.initHandlers()
进行初始化,并注册所有响应事件处理函数。
(2) socket .io发送登陆请求:login:
var onConnectOK = function(){
console.log("onConnectOK");
var sd = {
token:data.token,
roomid:data.roomid,
time:data.time,
sign:data.sign,
};
cc.vv.net.send("login",sd);
};
//启动服务
exports.start = function(conf,mgr){
config = conf;
var httpServer = require('http').createServer(app);
io = require('socket.io')(httpServer);
httpServer.listen(config.CLIENT_PORT);
//监听是否有客户端连接进来,如果有客户连接进来就会调用这个函数
//为这个客户创建一个socket通道
io.sockets.on('connection',function(socket){
//监听一个事件,然后data,客户端发送过来的数据
//数据使用的是json协议的编码,来进行数据交换;底层发送json文本;
socket.on('login',function(data){
//转成json格式数据
data = JSON.parse(data);
if(socket.userId != null){
//已经登陆过的就忽略
return;
}
var token = data.token;
var roomId = data.roomid;
var time = data.time;
var sign = data.sign;
console.log(roomId);
console.log(token);
console.log(time);
console.log(sign);
//检查参数合法性
if(token == null || roomId == null || sign == null || time == null){
console.log(1);
socket.emit('login_result',{errcode:1,errmsg:"invalid parameters"});
return;
}
//检查参数是否被篡改
var md5 = crypto.md5(roomId + token + time + config.ROOM_PRI_KEY);
if(md5 != sign){
console.log(2);
//emit发送一个事件
socket.emit('login_result',{errcode:2,errmsg:"login failed. invalid sign!"});
return;
}
//检查token是否有效
if(tokenMgr.isTokenValid(token)==false){
console.log(3);
socket.emit('login_result',{errcode:3,errmsg:"token out of time."});
return;
}
//检查房间合法性
var userId = tokenMgr.getUserID(token);
var roomId = roomMgr.getUserRoom(userId);
userMgr.bind(userId,socket);
socket.userId = userId;
//返回房间信息
var roomInfo = roomMgr.getRoom(roomId);
var seatIndex = roomMgr.getUserSeat(userId);
roomInfo.seats[seatIndex].ip = socket.handshake.address;
var userData = null;
var seats = [];
for(var i = 0; i < roomInfo.seats.length; ++i){
var rs = roomInfo.seats[i];
var online = false;
if(rs.userId > 0){
online = userMgr.isOnline(rs.userId);
}
seats.push({
userid:rs.userId,
ip:rs.ip,
score:rs.score,
name:rs.name,
online:online,
ready:rs.ready,
seatindex:i
});
if(userId == rs.userId){
userData = seats[i];
}
}
//通知前端
var ret = {
errcode:0,
errmsg:"ok",
data:{
roomid:roomInfo.id,
conf:roomInfo.conf,
numofgames:roomInfo.numOfGames,
seats:seats
}
};
socket.emit('login_result',ret);
//通知其它客户端
userMgr.broacastInRoom('new_user_comes_push',userData,userId);
socket.gameMgr = roomInfo.gameMgr;
//玩家上线,强制设置为TRUE
socket.gameMgr.setReady(userId);
socket.emit('login_finished');
if(roomInfo.dr != null){
var dr = roomInfo.dr;
var ramaingTime = (dr.endTime - Date.now()) / 1000;
var data = {
time:ramaingTime,
states:dr.states
}
userMgr.sendMsg(userId,'dissolve_notice_push',data);
}
});
a> 检查请求参数的合法性;
b> 绑定 uid
与 socket
,确保客户端与服务器的连接稳定并能够正确识别用户身份。
userMgr.bind(userId,socket);
socket.userId = userId;
c> 获取当前玩家的房间座位号,并获取房间中其他玩家的座位信息及数据。
//返回房间信息
var roomInfo = roomMgr.getRoom(roomId);
var seatIndex = roomMgr.getUserSeat(userId);
roomInfo.seats[seatIndex].ip = socket.handshake.address;
d> 发送 login_result
消息至前端,将游戏信息及座位数据传递给客户端。
e> 前端接收 login_result
响应,将游戏数据保存到本地;
f> 广播 new_user_comes_push
事件,通知房间内其他玩家有新玩家加入;
g> 触发登录结束事件,进入麻将游戏场景。
服务端加入房间逻辑
room_service.js
中实现进入房间的逻辑。
var enterRoomReq = function(serverinfo){
http.get(serverinfo.ip,serverinfo.httpPort,"/enter_room",reqdata,function(ret,data){
console.log(data);
if(ret){
if(data.errcode == 0){
db.set_room_id_of_user(userId,roomId,function(ret){
fnCallback(0,{
ip:serverinfo.clientip,
port:serverinfo.clientport,
token:data.token
});
});
}
else{
console.log(data.errmsg);
fnCallback(data.errcode,null);
}
}
else{
fnCallback(-1,null);
}
});
};
db.get_room_addr
:查找 roomid
所对应的麻将服务器的 IP
和端口;
enterRoomReq
函数:向麻将服务器发送请求至 http_service.js
的 "/enter_room"
接口;
- 麻将服务器上的
http_service.js
处理玩家进入房间的逻辑,并返回该房间的详细信息;
- 将麻将服务器信息及登录
token
返回给客户端,客户端开始执行登录到麻将服务器的流程。
创建房间
1:Hall.js的函数:onCreateRoomClicked;
2.CreateRoomWin
节点(CreateRoom
)上挂载的脚本文件:CreateRoom.js
。
3.createRoomWin
对应的节点名称为 CreateRoom
,该节点上挂载的脚本文件是 CreateRoom.js
。
cc.Class({
extends: cc.Component,
properties: {
// foo: {
// default: null,
// url: cc.Texture2D, // optional, default is typeof default
// serializable: true, // optional, default is true
// visible: true, // optional, default is true
// displayName: 'Foo', // optional
// readonly: false, // optional, default is false
// },
// ...
_leixingxuanze: null,
_gamelist: null,
_currentGame: null,
},
// use this for initialization
onLoad: function () {
this._gamelist = this.node.getChildByName('game_list');
this._leixingxuanze = [];
var t = this.node.getChildByName("leixingxuanze");
for (var i = 0; i < t.childrenCount; ++i) {
var n = t.children[i].getComponent("RadioButton");
if (n != null) {
this._leixingxuanze.push(n);
}
}
},
onBtnBack: function () {
this.node.active = false;
},
onBtnOK: function () {
var usedTypes = ['xzdd', 'xlch'];
var type = this.getType();
if (usedTypes.indexOf(type) == -1) {
return;
}
this.node.active = false;
this.createRoom();
},
getType: function () {
var type = 0;
for (var i = 0; i < this._leixingxuanze.length; ++i) {
if (this._leixingxuanze[i].checked) {
type = i;
break;
}
}
if (type == 0) {
return 'xzdd';
}
else if (type == 1) {
return 'xlch';
}
return 'xzdd';
},
getSelectedOfRadioGroup(groupRoot) {
console.log(groupRoot);
var t = this._currentGame.getChildByName(groupRoot);
var arr = [];
for (var i = 0; i < t.children.length; ++i) {
var n = t.children[i].getComponent("RadioButton");
if (n != null) {
arr.push(n);
}
}
var selected = 0;
for (var i = 0; i < arr.length; ++i) {
if (arr[i].checked) {
selected = i;
break;
}
}
return selected;
},
createRoom: function () {
var self = this;
var onCreate = function (ret) {
if (ret.errcode !== 0) {
cc.vv.wc.hide();
//console.log(ret.errmsg);
if (ret.errcode == 2222) {
cc.vv.alert.show("提示", "钻石不足,创建房间失败!");
}
else {
cc.vv.alert.show("提示", "创建房间失败,错误码:" + ret.errcode);
}
}
else {
cc.vv.gameNetMgr.connectGameServer(ret);
}
};
var type = this.getType();
var conf = null;
if (type == 'xzdd') {
conf = this.constructSCMJConf();
}
else if (type == 'xlch') {
conf = this.constructSCMJConf();
}
conf.type = type;
var data = {
account: cc.vv.userMgr.account,
sign: cc.vv.userMgr.sign,
conf: JSON.stringify(conf)
};
console.log(data);
cc.vv.wc.show("正在创建房间");
cc.vv.http.sendRequest("/create_private_room", data, onCreate);
},
constructSCMJConf: function () {
var wanfaxuanze = this._currentGame.getChildByName('wanfaxuanze');
var huansanzhang = wanfaxuanze.children[0].getComponent('CheckBox').checked;
var jiangdui = wanfaxuanze.children[1].getComponent('CheckBox').checked;
var menqing = wanfaxuanze.children[2].getComponent('CheckBox').checked;
var tiandihu = wanfaxuanze.children[3].getComponent('CheckBox').checked;
var difen = this.getSelectedOfRadioGroup('difenxuanze');
var zimo = this.getSelectedOfRadioGroup('zimojiacheng');
var zuidafanshu = this.getSelectedOfRadioGroup('zuidafanshu');
var jushuxuanze = this.getSelectedOfRadioGroup('xuanzejushu');
var dianganghua = this.getSelectedOfRadioGroup('dianganghua');
var conf = {
difen:difen,
zimo:zimo,
jiangdui:jiangdui,
huansanzhang:huansanzhang,
zuidafanshu:zuidafanshu,
jushuxuanze:jushuxuanze,
dianganghua:dianganghua,
menqing:menqing,
tiandihu:tiandihu,
};
return conf;
},
// called every frame, uncomment this function to activate update callback
update: function (dt) {
var type = this.getType();
if (this.lastType != type) {
this.lastType = type;
for (var i = 0; i < this._gamelist.childrenCount; ++i) {
this._gamelist.children[i].active = false;
}
var game = this._gamelist.getChildByName(type);
if (game) {
game.active = true;
}
this._currentGame = game;
}
},
});
创建房间步骤:
1> 从输入框中获取房间参数配置;
2> 发送请求至大厅服务器的 "/create_private_room"
接口,包含账号信息及房间配置参数。
3>服务器创建房间,返回房间的ID号, 连接IP地址与端口:
//创建一个房间
app.get('/create_private_room',function(req,res){
//验证参数合法性
var data = req.query;
//验证玩家身份
if(!check_account(req,res)){
return;
}
var account = data.account;
data.account = null;
data.sign = null;
var conf = data.conf;
//从数据库里面查询玩家数据
db.get_user_data(account,function(data){
if(data == null){
http.send(res,1,"system error");
return;
}
var userId = data.userid;
var name = data.name;
//验证玩家状态
db.get_room_id_of_user(userId,function(roomId){
if(roomId != null){
http.send(res,-1,"user is playing in room now.");
return;
}
//创建房间
room_service.createRoom(account,userId,conf,function(err,roomId){
if(err == 0 && roomId != null){
room_service.enterRoom(userId,name,roomId,function(errcode,enterInfo){
if(enterInfo){
var ret = {
roomid:roomId,
ip:enterInfo.ip,
port:enterInfo.port,
token:enterInfo.token,
time:Date.now()
};
ret.sign = crypto.md5(ret.roomid + ret.token + ret.time + config.ROOM_PRI_KEY);
http.send(res,0,"ok",ret);
}
else{
http.send(res,errcode,"room doesn't exist.");
}
});
}
else{
http.send(res,err,"create failed.");
}
});
});
});
});
room_service.createRoom(account,userId,conf,function(err,roomId){
4> 服务器响应后,客户端调用回调函数 onCreate
进行后续处理。
http.send(res,0,"ok",ret);
5> 若返回有错误信息,则显示提示;否则,直接连接至麻将服务器;
6> 按照加入房间的流程继续执行后续逻辑。
服务端创建房间逻辑:
get_user_data
:从 t_users
表中获取用户的游戏账号数据;
db.get_room_id_of_user
:获取当前用户的房间 ID
,若已在房间,则必须先退出该房间;
room_service.createRoom
创建房间:
1> 获取当前负载最低的服务器;
2> 检查玩家的房卡数量是否足够;
3> 将请求发送至麻将服务器的 http_service.js
,接口:/create_room
;
4> 麻将服务器中的 roommgr.js
处理该请求,通过 roomMgr.createRoom
创建房间,并返回 roomid
;
5> 在大厅的 room_server.js
中执行进入当前房间的逻辑。