这是多年前写的小游戏初版,游戏逻辑部分后来已经重构,变成了支持通用塔防游戏的结构,重构版源码后续整理好再介绍,这里先介绍下网络消息、创建房间部分逻辑。 下面是之前打包的初步版本。
联机版植物大战虫子游戏下载地址http://yun.baidu.com/share/link?shareid=2456982233&uk=3442849180
游戏方法:
1,双击开启服务器 EngineDemoServer_Release.exe。(服务器ip和端口配置在data\Sys\server.ini)
2,双击开启客户端 EngineDemoClient_Release。 一般开启两个客户端创建房间进行游戏。也可以开启一个客户端然后创建ai玩家进行游戏。
测试用登录id test** (注意重复登录会被踢),测试用登录密码 1111
EngineDemoRobotClient_Release.exe是测试用机器人客户端,可选择性开启
截图
服务器
多线程安全问题。接收网络包为了提高吞吐量一般放在子线程中,此时若直接处理消息包,如果需要调用标准的windows控件来显示是不起作用的,如果调用引擎的其它接口比如执行脚本甚至会引起崩溃。所以在子线程收到消息包时将其保存到对列,主线程循环中再从队列弹出并处理,注意对列操作前要加锁。
另一篇文章单独介绍了消息封包和IOCP,这里不再重复。
客户端网络部分
//========================================================
// @Date: 2016.05
// @File: Include/Net/NetClient.h
// @Brief: NetClient
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#pragma once
#ifndef __NetClient__H__
#define __NetClient__H__
#include "General/singleton.h"
#define NET_CLIENT_PORT_MIN 10001
#define NET_CLIENT_PORT_MAX 20001
#define G_Client NetClient::GetSingleton()
class PacketQueue;
class PacketBase;
class TcpStream;
typedef void* PSocket;
#include "General/Thread.h"
typedef void (*OutPutFun)(const char *msg);
//?? 可能多个实体 连接多个服务器game chat? 代理模式?
class NetClient:public MemberSingleton<NetClient>
{
public:
NetClient();
~NetClient();
//!子线程可调用,控制台可以立即输出,但ui无法立即刷新,需要主线程异步处理
void LogSub(const char* lpszFormat, ...);
void SetLogFun(OutPutFun fun);
bool InitNetwork(const char *serv_addr, unsigned int serv_port);
bool Close();
//!向服务器发消息
bool SendMsg(int packetID, char* buffer, int bufferSize);
bool SendPacketToServer( PacketBase* packet);
//for inner server
int InnerRecvPacket( PacketBase* packet );
int RecvStream( PSocket socket, char* buffer, int bufferSize );
void SetSpecialPacketID(int login,int disconnect);
#ifdef WIN32APP
//!线程回调
int RecvThreadProc( void* threadParam );
void* m_receiveThread;
#endif
#ifdef ANDROIDAPP
//!网络环境在android中用java开启
//!网络开启是否成功
void SetRunning(bool running);
//!处理tcp流
int AndroidTcpStream(int streamSize,const char* stream);
#endif
//!处理消息队列
void MainThreadProcessPacketPool();
static const char* classname(){return "NetClient";}
PacketQueue* m_packetQueue;
PSocket m_socket;
char m_serverAddress[256];
unsigned int m_serverPort;
unsigned int m_port;
//1: connected to net server
//0: connected to inner server
bool m_bConnecting;
//断开协议id
int m_disconnectPacketID;
OutPutFun m_logFun;
char m_logBuff[1024*10];
int m_logSize;
CriticalSection m_logCriticalSection;
//!64k合设置的系统缓存一样大,可以大于(浪费),可以小于(低效)
char* m_receiveBuffer;
TcpStream* m_tcpStream;
//有些消息阻塞后续消息的发送,比如登录
bool m_waitingPacket;
//
#define MaxPingCount 8
int m_iPingCount;
float m_fPingLatency[MaxPingCount];
float m_fLastPingTime;
float m_fPingLatencyAvg;
};
#endif
//========================================================
// @Date: 2016.05
// @File: Include/Net/NetClient.h
// @Brief: NetClient
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#pragma once
#ifndef __NetRobotClient__H__
#define __NetRobotClient__H__
#include "General/singleton.h"
#define NET_CLIENT_PORT_MIN 10001
#define NET_CLIENT_PORT_MAX 20001
class PacketQueue;
class PacketBase;
class TcpStream;
//
typedef void* PSocket;
#include "General/Thread.h"
typedef void (*OutPutFun)(const char *msg);
#define NET_ROBOTCLIENT_PORT_MIN 6000
#define NET_ROBOTCLIENT_PORT_MAX 9000
//模拟客户端的机器人
class NetRobot
{
public:
friend class NetRobotsClient;
NetRobot();
virtual ~NetRobot();
virtual void Update(){};
virtual void* RelocateSyncGameInfo(){return NULL;};
bool InitNetwork(const char *serv_addr, unsigned int serv_port);
bool Close();
//!向服务器发消息
bool SendMsg(int packetID, char* buffer, int bufferSize);
void SendPacketToServer( PacketBase* packet);
int RecvStream( PSocket socket, char* buffer, int bufferSize );
void Receive();
//protected:
PSocket m_socket;
//!自己的座位号
int m_playerID;
unsigned int m_port;
int m_index;
char m_name[128];
bool m_bConnecting;
//!每个socket配备独立缓冲区,减小缓冲可以使机器人占用内存减少
//!64k合设置的系统缓存一样大,可以大于(浪费),可以小于(低效)
char* m_receiveBuffer;
TcpStream* m_tcpStream;
bool m_waitingPacket;//某些消息在没收到反馈前不能发第二次
};
//若干机器人共用一个线程,否则线程开多了会卡(一个线程至少1M的栈),因此不能在进程中直接开多个客户端。
//模拟多个机器人的客户端
class NetRobotsClient:public MemberSingleton<NetRobotsClient>
{
public:
NetRobotsClient();
PacketQueue* m_packetPool;
char m_serverAddress[256];
unsigned int m_serverPort;
//!子线程可调用,控制台可以立即输出,但ui无法立即刷新,需要主线程异步处理
void LogSub(const char* lpszFormat, ...);
//!或者使用virtual fun
void SetLogFun(OutPutFun fun);
virtual const char* GetPacketLogStr(PacketBase* packet);
template <class Robot>
/*virtual*/bool InitRobot(int robotNum);
NetRobot* GetRobot(const char* name);
NetRobot* GetRobot(int playerID);
//NetRobot* GetRobot(int index);
bool InitNetwork(const char *serv_addr, unsigned int serv_port);
bool Close();
static const char* classname(){return "NetRobotsClient";}
//!线程回调
typedef struct ThreadParm
{
HANDLE pThread;
int index;
int startRobotIndex;
int endRobotIndex;
} ;
int MsgReceiverProc( void* threadParam );
HANDLE* m_receiveThread;
int m_receiveThreadNum;
//!处理消息队列
void MainThreadProcessPacketPool();
NetRobot** m_robots;
int m_robotNum;
bool m_bRunning;
OutPutFun m_logFun;
char m_logBuff[1024*10];
int m_logSize;
CriticalSection m_logCriticalSection;
};
template <class Robot>
bool NetRobotsClient::InitRobot(int robotNum)
{
m_robotNum = robotNum;
m_robots = new NetRobot*[m_robotNum];
for (int i=0;i<m_robotNum;i++)
{
m_robots[i] = new Robot;
m_robots[i]->m_index = i;
sprintf(m_robots[i]->m_name,"robot%04d",i);
}
return true;
}
#endif
//========================================================
// @Date: 2016.05
// @File: Include/Net/NetUdp.h
// @Brief: NetUdp
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#pragma once
#ifndef __NetUdp__H__
#define __NetUdp__H__
#include "General/singleton.h"
#define NET_CLIENT_PORT_MIN 10001
#define NET_CLIENT_PORT_MAX 20001
#define G_UdpPoint NetPointUdp::GetSingleton()
class PacketQueue;
class PacketBase;
typedef void* PSocket;
#include "General/Thread.h"
//UDP不存在粘包问题 send、recv个数是一致的
typedef void (*OutPutFun)(const char *msg);
class NetPointUdp:public MemberSingleton<NetPointUdp>
{
public:
NetPointUdp();
~NetPointUdp();
//!子线程可调用,控制台可以立即输出,但ui无法立即刷新,需要主线程异步处理
void LogSub(const char* lpszFormat, ...);
void SetLogFun(OutPutFun fun);
virtual const char* GetPacketLogStr(PacketBase* packet);
//无需指定端口
bool InitNetwork(int broadcastPort);
bool Close();
//!向服务器发udp 暂未实现 server必须在外网或同一nat,否则发不过去。在不同nat时服务器必须立刻返回消息,否则链路很短的时间内(200ms)将断开。
//!向某地址发udp 只能是同一nat
bool SendMsgToAdress(char* buffer, int bufferSize,const char* address,int port);
bool SendPacketToAdress( PacketBase* packet,const char* address,int port);
//!局域网udp广播 暂时只实现此处
bool SendPacketBroadcast( PacketBase* packet,int port);
int RecvBuffer( PSocket socket, char* buffer, int bufferSize );
#ifdef WIN32APP
//!线程回调
int RecvThreadProc( void* threadParam );
void* m_receiveThread;
#endif
//!处理消息队列
void MainThreadProcessPacketPool();
static const char* classname(){return "NetPointUdp";}
bool m_bRunning;
PSocket m_broadcastSocket;
PacketQueue* m_packetQueue;
char m_myAddress[256];
char m_hostName[256];
//广播到的端口,即对方侦听接收的端口,而自己发送的端口是自动分派的。
int BroadcastPort;
OutPutFun m_logFun;
char m_logBuff[1024*10];
int m_logSize;
CriticalSection m_logCriticalSection;
};
#endif
消息包处理
主循环消息包分发技巧。一种方法是在界面更新函数中处理消息队列,这样可以将一系列消息处理内聚到一起。可能存在的问题是大量不同的界面会无差别的处理相同的消息,以致很多消息要放到基类而形成一个超级类。所以此处将消息包处理通过文件来聚合,同时不必放在界面处理中,通过一个小的设计模式还可以避免一个很大的switch语句的使用,避免需要同时包含所有的消息。每个消息对应一个类,消息解析统一由服务器端编写,客户端负责检查并实现该类的处理函数。
游戏消息协议
游戏的初步构思是若干开放式小游戏在mmorpg的世界中进行,经过的玩家都可以观战到。
//========================================================
// @Date: 2016.05
// @File: SourceDemoServer/Packet/Protocol.h
// @Brief: Protocol
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#pragma once
#ifndef __Protocol__H__
#define __Protocol__H__
#define PlayerNameLenMax 32
#define RoomNameLenMax 32
#define LobbyNameLenMax 32
#define IPAddressMax 16
//即时刷新过滤,商城道具列表基本不变无需刷新,俱乐部成员列表点击刷新,房间列表在打开列表界面时即时刷新
enum PacketUpdateFilter
{
PF_RoomListUpdate = 1,
PF_PlayerListUpdate = 1<<2,
};
//传输大的列表时将消息分包
enum PacketListFlag
{
List_Begin = 1,
List_Data = 2,
List_End = 4,
};
//一个ID将一系列功能相关的消息封装起来处理。
enum Protocol
{
//<<基本
BEGIN_NORMAL = 10000,
C2S_DisConnection ,//断开连接
S2C_ConnectionShutdown ,//被踢
//>>
//<<登录相关
C2S_Verificate ,//验证客户端合法性
S2C_Verificate ,
C2S_Regist ,//注册
S2C_Regist ,
C2S_Login ,//登录
S2C_Login ,
C2S_EnterLobby ,//进入大厅
S2C_EnterLobby ,//
C2S_ExitLobby ,//退出大厅
S2C_ExitLobby ,//
//>>
//<<聊天相关
C2S_Chat ,//聊天
S2C_Chat ,//
C2S_ChatPic ,//图片聊天,大消息
S2C_ChatPic ,//
C2S_ChatOption ,//聊天设置
S2C_ChatOption ,//
C2S_MsgList ,//消息列表
S2C_MsgList ,//
C2S_MsgListUpdate ,//移除 等
S2C_MsgListUpdate ,//添加 移除 变更等
//>>
//<<邮件相关
C2S_MailList ,//邮件列表
S2C_MailList ,//
//C2S_MailListUpdate ,//移除 等
S2C_MailListUpdate ,//增加 移除 接收 变更等
C2S_MailOP ,//移除 等
//S2C_MailOP ,//添加 移除 变更等
//>>
//<<玩家、好友相关
C2S_PlayerInfo ,//玩家信息
S2C_PlayerInfo ,//
C2S_PlayerList ,//玩家列表
S2C_PlayerList ,//
S2C_PlayerListUpdate ,//添加 移除 名字 位置变更等
C2S_FriendList ,//好友列表
S2C_FriendList ,//
C2S_FriendListUpdate ,//添加 移除 位置变更等
S2C_FriendListUpdate ,//
//>>
//<<RPG游戏内相关
S2C_PlayerBaseInfo ,//玩家基本信息
S2C_PlayerVisible ,//玩家进入退出视野 monster npc?
C2S_PlayerMove ,//玩家移动,只给在其视野内的玩家发送
S2C_PlayerMove ,
C2S_PlayerPoint ,//玩家点数
S2C_PlayerPoint ,
C2S_PlayerAnim ,//玩家动画
S2C_PlayerAnim ,
C2S_PlayerState ,//玩家状态
S2C_PlayerState ,
S2C_NpcVisible ,//npc 单向消息
S2C_NpcMove ,
S2C_NpcAnim,
S2C_NpcState,
S2C_MonsterVisible ,//monster 单向消息
S2C_MonsterMove ,
C2S_MonsterHurt ,//monster 点数
S2C_MonsterHurt ,
S2C_MonsterAnim,
S2C_MonsterState,
C2S_UsingList ,
S2C_UsingList ,
C2S_Using ,//物品操作,具体操作见操作码 :捡取、npc处购买出售、摆摊购买出售、使用、other使用(比如给其他玩家加血)
S2C_Using ,
C2S_WeaponList ,
S2C_WeaponList ,
C2S_WearList ,
S2C_WearList ,
C2S_Weapon ,//装备操作
S2C_Weapon ,
S2C_WeaponOther ,//其它玩家穿脱装备
C2S_MissionList ,
S2C_MissionList ,
C2S_Mission ,//任务操作
S2C_Mission ,
C2S_SkillList ,//已学技能列表
S2C_SkillList ,
C2S_Skill ,//技能操作
S2C_Skill ,
S2C_OtherSkill ,//其它玩家、宠物释放、打断技能
C2S_ShortcutList ,//快捷槽列表
S2C_ShortcutList ,
C2S_Shortcut ,//快捷槽操作
S2C_Shortcut ,
C2S_Bag ,//背包操作
C2S_Fight ,//战斗操作
//>>
//<<小游戏房间相关
C2S_RoomList ,//房间列表
S2C_RoomList ,//
S2C_RoomListUpdate ,//列表跟新:添加 移除 名字 状态 成员变更等。 只给打开了房间列表界面的玩家发送。房间列表更新频度,房间个数r,玩家个数n,平均视野内玩家个数v,前者复杂度rXn,后者nXv(?一帧内变化的房间一起发)
C2S_CreateRoom ,//创建房间
S2C_CreateRoom ,//自己创建
C2S_EnterRoom ,//进入房间
S2C_EnterRoom ,//创建后进入或选择进入
S2C_OtherEnterRoom ,
C2S_CreateAiRoomPlayer ,//主机创建ai玩家并进入房间
S2C_CreateAiRoomPlayer ,
S2C_AiEnterRoom ,
C2S_ExitRoom ,//退出房间
S2C_ExitRoom ,
C2S_KickOtherRoomPlayer ,//房主踢人 或踢ai玩家
S2C_OtherExitRoom ,//别人退出房间 ?? 利用S2C_RoomPlayerUpdate
C2S_RoomUpdate ,//房主改变,房间类型,名字等改变
S2C_RoomUpdate ,//
C2S_RoomPlayerUpdate ,//玩家avatar改变,房主,队伍位置改变等
S2C_RoomPlayerUpdate ,//
//S2C_RoomPlayerListUpdate ,//不添加该消息因为仅可以代替S2C_OtherEnterRoom S2C_OtherExitRoom
//>>
//<<小游戏相关
//一个玩家不可以多视口同时进行两个小游戏,因为只能处在一个房间中
//小游戏内部消息添加命令类型
C2S_MiniPlayerReady ,//玩家准备好
S2C_MiniPlayerReady ,
S2C_MiniGameReady ,//游戏准备好
C2S_MiniGameStart ,//房主点击游戏开始
S2C_MiniGameStart ,//
C2S_MiniGameStartRes ,//某客户端开启失败
C2S_MiniGameEnd ,//房主端判断游戏结束
S2C_MiniGameEnd ,//
C2S_MiniGameCmd ,//游戏内命令,客户端发给服务器要求转发房间内其它人
C2S_MiniGameCmdAll ,//游戏内命令,客户端发给服务器要求转发房间内所有人
S2C_MiniGameCmd ,
//<<不需要以下消息
//C2S_MiniGameCmd_2H ,//客户端发给服务器要求转发主机
//C2S_MiniGameCmd_2Other ,//客户端发给服务器要求转发房间内其它所有人
//S2C_MiniGameCmd_H2 ,//主机发给服务器要求转发房间内其它所有人
//S2C_MiniGameCmd_C2 ,//客户端发给服务器要求转发房间内其它所有人
//C2S_MiniGameAICmd ,//主机客户端上的ai玩家发给服务器要求转发,和主机真人具有相同socket。 直接使用C2S_MiniGameCmd即可
//S2C_MiniGameAICmd ,
//主机ai发addplant给server,server要转发屏蔽主机是可以的,主机上ai玩家和主机使用的是同一个游戏环境,此时已经是新的环境了
//其它玩家发addplant给server,server只要转发一份给主机,即使主机有ai
//命令可以带有发送者字段,发送者客户端添加
//>>
//<<小游戏观战相关
//观战玩家可以看到minigame中的人在玩vr游戏? 给这些人带上vr头盔标志?
//一个玩家可以同时看到多个minigame?(最多可以设置上限,服务器是否限制某片区域内minigame数量?比如若干房间都想在一个地点进行赛车游戏)
//C2S_PlayerReady ,//玩家准备好
//S2C_PlayerReady ,
//S2C_GameReady ,//游戏准备好
C2S_MiniGameOtherOption ,//设置不观战黑名单的游戏
S2C_MiniGameOtherVisible ,//
//S2C_MiniGameOtherEnd ,//use visible
C2S_MiniGameOtherCmd ,//观战游戏内命令
S2C_MiniGameOtherCmd ,
//>>
//<<活动相关
C2S_EventList ,//活动列表
S2C_EventList ,//
C2S_EventPlayerInfo ,//单个活动及玩家相关信息
S2C_EventPlayerInfo ,//
C2S_EventPlayerOp ,//活动中玩家操作
S2C_EventPlayerOp ,//
//>>
C2S_PacketUpdateFilter ,//即时过滤开关
UDP_S2L_LanServerCreate ,//创建局域网服务器时发送局域网广播,以便同局域网的客户端可以发现并联机
UDP_S2L_LanServerClose ,
UDP_C2L_LanClientSearchServer ,//客户端启动或刷新lanserver列表时请求,收到的此消息的lanserver回复UDP_LanServerCreate
END_MAX,
};
//通用错误码
enum
{
Err_WrongMoney = -11, //金币钱不足
Err_UnKnow = -999, //未知错误
};
#endif // _PROTOCOL_PACKETID_H
植物大战虫子小游戏内部命令
enum MiniPVBCmd
{
CMD_PlantAdd, //种植植物
CMD_PlantDead, //植物死亡
CMD_BugAdd, //产生虫子
CMD_BugDead, //虫子死亡
CMD_BugMove, //虫子移动
CMD_Anim, //播放动画
};
后续对界面做了改版,ui是自己p的图,改来改去就是不好看,将就着用了。
rpg玩家可以参与小游戏内使用技能杀虫子的构思被砍掉了,可能会破坏塔防类游戏的玩法。
服务器端房间相关消息处理:写的不好,仅供参考。游戏核心逻辑还没动头呢就要先写一堆基础代码,不是一班的烦。
//========================================================
// @Date: 2016.05
// @File: SourceDemoServer/Packet/PacketRoomServer.cpp
// @Brief: PacketRoomServer
// @Author: LouLei
// @Email: twopointfive@163.com
// @Copyright (Crapell) - All Rights Reserved
//========================================================
#include "General/Pch.h"
#include "Net/NetServerIocp.h"
#include "Game/NetPlayer.h"
#include "Game/NetRoom.h"
#include "Game/NetLobby.h"
#include "Packet/Protocol.h"
#include "Packet/PacketRoom.h"
#include "Packet/PacketPlayerFriend.h"
#include "Rpg/MiniGameStyle.h"
#include "Game/NetWeapon.h"
#include "General/Pce.h"
//==================^_^==================^_^==================^_^==================^_^
bool C2SPacketRoomList::Process()
{
NetPlayer* fromPlayer = G_Lobby->GetPlayerBySocket(m_fromSocket);
NetRoomList& sendList = G_Lobby->m_roomList;
NetRoomList::iterator it = sendList.begin();
int flag = 0;
S2CPacketRoomList packet;
int accumNum = 0;
int curNum = 0;
for ( ; it!=sendList.end();it++ )
{
//if ( (*it)->m_playerLocation != PL_OFFLINE)
{
if (accumNum==0)
{
flag |= List_Begin;
}
if (accumNum==sendList.size()-1)
{
flag |= List_End;
}
//
LobbyRoomInfo& roominfo = packet.roomInfos[curNum];
strcpy(roominfo.roomName,(*it)->m_roomName);
roominfo.roomID = (*it)->m_roomID;
roominfo.ownerID = (*it)->m_chiefPlayerID;
roominfo.roomType = (*it)->m_roomType;
roominfo.roomState = (*it)->m_roomState;
//
accumNum++;
curNum++;
if (curNum==MaxRoomList
|| flag&List_End
)
{
packet.infoNum = curNum;
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
flag = 0;
curNum = 0;
}
}
}
return true;
}
//==================^_^==================^_^==================^_^==================^_^
bool C2SPacketCreateRoom::Process()
{
NetPlayer* fromPlayer = G_Lobby->GetPlayerBySocket(m_fromSocket);
if(fromPlayer==NULL)
{
G_Server->LogSub("[%d] C2SPacketCreateRoom玩家不存在。\n",m_fromSocket);
return false;
}
if(fromPlayer->m_roomID!=-1)
{
S2CPacketCreateRoom packet;
packet.m_res = S2CPacketCreateRoom::Err_InRoom;
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketCreateRoom已经在房间内。\n",roomType);
return false;
}
MiniGameStyle* miniGameStyle = G_StyleMgr->GetStyle<MiniGameStyle>(roomType);
if (miniGameStyle==NULL)
{
S2CPacketCreateRoom packet;
packet.m_res = S2CPacketCreateRoom::Err_NoRoomType;
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketCreateRoom房间类型不存在。\n",roomType);
return false;
}
//int roomID = fromPlayer->m_playerKey; //bug 房主退出后新建房间id重复
//int roomID = G_Lobby->m_roomList.size(); //bug 0 1 2; 1room解散后 新建的2重复
//ASSERT G_Lobby->GetRoom(roomID)==NULL;
int roomID = G_Lobby->NextValidRoomID();
NetRoom* room = new NetRoom;
room->m_roomID = roomID;
room->m_chiefPlayerID = fromPlayer->ObjID();
room->m_roomType = (MiniGameRoomType)roomType;
room->m_maxPlayerNum = miniGameStyle->maxPlayerNum;
room->m_sideNum = miniGameStyle->sideNum;
if (room->m_maxPlayerNum<=0)
{
//至少1个人
room->m_maxPlayerNum = 1;
}
strcpy(room->m_roomName,roomName);
G_Lobby->AddRoom(room);
{
//
S2CPacketCreateRoom packet;
packet.roomID = roomID;
packet.roomType = roomType;
strcpy(packet.roomName,roomName);
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
}
{
//创建后进入
room->AddPlayer(fromPlayer);
fromPlayer->m_bAi = false;
S2CPacketEnterRoom packet;
packet.roomID = roomID;
packet.roomType = (MiniGameRoomType)roomType;
packet.chiefPlayerID = fromPlayer->ObjID();
packet.roomSlot = fromPlayer->m_roomSlot;
strcpy(packet.roomName,roomName);
//此时应该只有一个人
MyRoomInfo* info = G_SyncMyRoomInfo;
info->m_roomPlayers.clear();
MyRoomPlayerInfo playerinfo;
NetPlayer* roomPlayer;
for (int i=0;i<MaxRoomPlayer;++i)
{
if (room->m_players[i])
{
roomPlayer = room->m_players[i];
playerinfo.roomSlot = roomPlayer->m_roomSlot;
strcpy(playerinfo.playerName,roomPlayer->m_playerName);
playerinfo.playerID = roomPlayer->ObjID();
playerinfo.level = roomPlayer->m_level;
playerinfo.isAI = roomPlayer->m_bAi;
strcpy(playerinfo.icon,roomPlayer->m_headIcon);
//my avatar没必要发
playerinfo.style = roomPlayer->GetStyle()->ID;
WeaponPart* weaponPart = roomPlayer->GetPart<WeaponPart>();
playerinfo.weaponNum = weaponPart->m_weaponWearList.size();
int i = 0;
for (NetWeaponPtrList::iterator it=weaponPart->m_weaponWearList.begin();it!=weaponPart->m_weaponWearList.end();++it)
{
playerinfo.weaponStyle[i] = (*it)->StyleID();
playerinfo.weaponID[i] = (*it)->ObjID();
i++;
}
info->m_roomPlayers.push_back(playerinfo);
}
}
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
}
{
//房间列表改变
S2CPacketRoomListUpdate packet;
packet.updateType = S2CPacketRoomListUpdate::Room_Add;
packet.roominfo.roomID = roomID;
packet.roominfo.roomType = roomType;
packet.roominfo.ownerID = room->m_chiefPlayerID;
strcpy(packet.roominfo.roomName,roomName);
G_Lobby->SendPacketToLobbyOther(&packet,fromPlayer);
}
return true;
}
//==================^_^==================^_^==================^_^==================^_^
bool C2SPacketEnterRoom::Process()
{
NetPlayer* fromPlayer = G_Lobby->GetPlayerBySocket(m_fromSocket);
if(fromPlayer==NULL)
{
G_Server->LogSub("[%d] C2SPacketEnterRoom玩家不存在。\n",m_fromSocket);
return false;
}
NetRoom* room = G_Lobby->GetRoom(roomID);
if(room==NULL)
{
S2CPacketEnterRoom packet;
packet.roomID = roomID;
packet.m_res = S2CPacketEnterRoom::Err_NoRoom;//房间不存在
//packet.roomType = 0;
//strcpy(packet.roomName,roomName);
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketEnterRoom房间不存在。\n",roomID);
return false;
}
if (fromPlayer->m_roomID==roomID)
{
S2CPacketEnterRoom packet;
packet.roomID = roomID;
packet.m_res = S2CPacketEnterRoom::Err_AlreadyInRoom;//已经在房间内
//packet.roomType = 0;
//strcpy(packet.roomName,roomName);
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketEnterRoom已经在房间内。\n",roomID);
return false;
}
if (room->m_roomState==RS_Gaming)
{
S2CPacketEnterRoom packet;
packet.roomID = roomID;
packet.m_res = S2CPacketEnterRoom::Err_Gaming;//游戏中
//packet.roomType = 0;
//strcpy(packet.roomName,roomName);
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketEnterRoom游戏中。\n",roomID);
return false;
//如果类似rpg,游戏进行中玩家也可以随意进入退出游戏,房间就变成了‘任务房间’、‘副本房间’。
//去掉return,给当事人发送进入房间消息后,再发送游戏开始消息。
}
if (room->IsFull())
{
S2CPacketEnterRoom packet;
packet.roomID = roomID;
packet.m_res = S2CPacketEnterRoom::Err_FullRoom;//满员
//packet.roomType = 0;
//strcpy(packet.roomName,roomName);
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketEnterRoom房间满员。\n",roomID);
return false;
}
int res = room->AddPlayer(fromPlayer);
if (res!=0)
{
return false;
}
else
{
fromPlayer->m_bAi = false;
{
//通知当事人
S2CPacketEnterRoom packet;
packet.m_res = 0;
packet.roomID = roomID;
packet.roomType = room->m_roomType;
strcpy(packet.roomName,room->m_roomName);
packet.chiefPlayerID = room->m_chiefPlayerID;
packet.roomSlot = fromPlayer->m_roomSlot;
MyRoomInfo* info = G_SyncMyRoomInfo;
info->m_roomPlayers.clear();
MyRoomPlayerInfo playerinfo;
NetPlayer* roomPlayer;
for (int i=0;i<MaxRoomPlayer;++i)
{
if (room->m_players[i])
{
roomPlayer = room->m_players[i];
playerinfo.roomSlot = roomPlayer->m_roomSlot;
strcpy(playerinfo.playerName,roomPlayer->m_playerName);
playerinfo.playerID = roomPlayer->ObjID();
playerinfo.level = roomPlayer->m_level;
strcpy(playerinfo.icon,roomPlayer->m_headIcon);
playerinfo.isAI = roomPlayer->m_bAi;
//avatar
if (roomPlayer->m_bAi)
{
playerinfo.style = dynamic_cast<MiniAiNetPlayer*>(roomPlayer)->m_npcStyle;
}
else
{
playerinfo.style = roomPlayer->GetStyle()->ID;
}
WeaponPart* weaponPart = roomPlayer->GetPart<WeaponPart>();
playerinfo.weaponNum = weaponPart->m_weaponWearList.size();
int i = 0;
for (NetWeaponPtrList::iterator it=weaponPart->m_weaponWearList.begin();it!=weaponPart->m_weaponWearList.end();++it)
{
playerinfo.weaponStyle[i] = (*it)->StyleID();
playerinfo.weaponID[i] = (*it)->ObjID();
i++;
}
info->m_roomPlayers.push_back(playerinfo);
}
}
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
}
{
//通知房间内其它玩家
S2CPacketOtherEnterRoom packet;
packet.m_res = 0;
packet.roomID = roomID;
packet.playerID = fromPlayer->ObjID();
packet.roomSlot = fromPlayer->m_roomSlot;
packet.level = fromPlayer->m_level;
strcpy(packet.playerName,fromPlayer->m_playerName);
//avatar
packet.style = fromPlayer->GetStyle()->ID;
WeaponPart* weaponPart = fromPlayer->GetPart<WeaponPart>();
packet.weaponNum = weaponPart->m_weaponWearList.size();
int i = 0;
for (NetWeaponPtrList::iterator it=weaponPart->m_weaponWearList.begin();it!=weaponPart->m_weaponWearList.end();++it)
{
packet.weaponStyle[i] = (*it)->StyleID();
packet.weaponID[i] = (*it)->ObjID();
i++;
}
room->SendPacketToRoomOther(&packet,fromPlayer);
}
{
//通知大厅内其它玩家房间列表改变
S2CPacketRoomListUpdate packet;
packet.updateType = S2CPacketRoomListUpdate::Room_UpdateMember;
packet.roominfo.roomID = roomID;
G_Lobby->SendPacketToLobbyAll(&packet);
}
fromPlayer->m_playerLocation = PL_INROOM;
{
//玩家列表改变
S2CPacketPlayerListUpdate packet;
packet.updateType = S2CPacketPlayerListUpdate::Player_UpdateLocation;
packet.playerinfo.playerID = fromPlayer->ObjID();
packet.playerinfo.playerLocation = fromPlayer->m_playerLocation;
G_Lobby->SendPacketToLobbyAll(&packet);
}
}
return true;
}
//==================^_^==================^_^==================^_^==================^_^
bool C2SPacketCreateAiRoomPlayer::Process()
{
NetPlayer* fromPlayer = G_Lobby->GetPlayerBySocket(m_fromSocket);
if(fromPlayer==NULL)
return false;
NetRoom* room = G_Lobby->GetRoom(roomID);
if(room==NULL)
{
S2CPacketCreateAiRoomPlayer packet;
packet.m_res = S2CPacketCreateAiRoomPlayer::Err_NoRoom;//房间不存在
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketCreateAiRoomPlayer房间不存在。\n",roomID);
return false;
}
if(room->m_chiefPlayerID != fromPlayer->ObjID())
{
S2CPacketCreateAiRoomPlayer packet;
packet.m_res = S2CPacketCreateAiRoomPlayer::Err_NotChief;//不是房主
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketCreateAiRoomPlayer不是房主。\n",roomID);
return false;
}
//ai玩家允许重名
//NetPlayer* aiplayer = room->GetPlayerByName(playerName);
//if(aiplayer!=NULL)
//{
// S2CPacketCreateAiRoomPlayer packet;
// packet.m_res = S2CPacketCreateAiRoomPlayer::Err_AlreadyName;//已经存在同名玩家
// G_Server->SendPacketToPlayer(&packet,m_fromSocket);
// return false;
//}
if (room->IsFull())
{
S2CPacketCreateAiRoomPlayer packet;
packet.m_res = S2CPacketCreateAiRoomPlayer::Err_FullRoom;//满员
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketCreateAiRoomPlayer房间满员。\n",roomID);
return false;
}
MiniAiNetPlayer* aiplayer = new MiniAiNetPlayer;
int res = room->AddPlayer(aiplayer);
if (res!=0)
{
delete aiplayer;
}
else
{
aiplayer->m_bAi = true;
aiplayer->m_npcStyle = npcStyle;
aiplayer->SetID(G_Lobby->NextValidMonsterID());
Ptr2Socket(aiplayer->m_socket) = Ptr2Socket(m_fromSocket);
sprintf(aiplayer->m_playerName,playerName);
static int test = 0;
//从数据库读取一系列数据
aiplayer->m_level = level;
sprintf(aiplayer->m_headIcon,"default%d",test%4);
test++;
//aiplayer->npcStyle = npcStyle;
{
//通知房间内所有玩家
S2CPacketAiEnterRoom packet;
packet.m_res = 0;
packet.roomID = roomID;
packet.playerID = aiplayer->ObjID();
packet.roomSlot = aiplayer->m_roomSlot;
packet.level = aiplayer->m_level;
strcpy(packet.playerName,aiplayer->m_playerName);
packet.style = npcStyle;
room->SendPacketToRoomAll(&packet,false);
}
{
//通知大厅内其它玩家房间列表改变
S2CPacketRoomListUpdate packet;
packet.updateType = S2CPacketRoomListUpdate::Room_UpdateMember;
packet.roominfo.roomID = roomID;
G_Lobby->SendPacketToLobbyAll(&packet);
}
}
return true;
}
//==================^_^==================^_^==================^_^==================^_^
bool C2SPacketExitRoom::Process()
{
//真人, ai退出会发C2SPacketKickOtherRoomPlayer
NetPlayer* fromPlayer = G_Lobby->GetPlayerBySocket(m_fromSocket);
if(fromPlayer==NULL)
{
//S2CPacketExitRoom packet;
//packet.m_res = S2CPacketExitRoom::Err_NotInRoom;//玩家不存在
//G_Server->SendPacketToPlayer(&packet,m_fromSocket);
//G_Server->LogSub("[%d] C2SPacketExitRoom玩家不存在。\n",playerID);
return false;
}
//assert fromPlayer->m_roomID == roomID
roomID = fromPlayer->m_roomID;
//如果游戏正在进行中,不会发生exit消息,而是直接发送gameend消息。
NetRoom* room = G_Lobby->GetRoom(roomID);
if(room==NULL)
{
S2CPacketExitRoom packet;
packet.m_res = S2CPacketExitRoom::Err_NoRoom;//房间不存在
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketExitRoom房间不存在。\n",roomID);
return false;
}
if(room->m_roomState == RS_Gaming)
{
S2CPacketExitRoom packet;
packet.m_res = S2CPacketExitRoom::Err_Gaming;//游戏进行中不能退出
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketExitRoom游戏进行中不能退出房间。\n",roomID);
return false;
}
int playerID = fromPlayer->ObjID();
int res = room->RemovePlayer(playerID);
if (res!=0)
{
S2CPacketExitRoom packet;
packet.m_res = S2CPacketExitRoom::Err_NotInRoom;//不在房间内
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketExitRoom不在房间内。\n",playerID);
return false;
}
else
{
if(room->GetRealPlayerNum()==0)
{
//最后一个退出,解散房间
G_Lobby->RemoveRoom(roomID);
{
//通知当事人
S2CPacketExitRoom packet;
packet.m_res = 0;
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
}
{
//通知大厅内其它玩家房间列表改变
S2CPacketRoomListUpdate packet;
packet.updateType = S2CPacketRoomListUpdate::Room_Remove;
packet.roominfo.roomID = roomID;
G_Lobby->SendPacketToLobbyAll(&packet);
}
{
fromPlayer->m_roomID = -1;
fromPlayer->m_playerLocation = PL_INLOBBY;
//玩家列表改变
S2CPacketPlayerListUpdate packet;
packet.updateType = S2CPacketPlayerListUpdate::Player_UpdateLocation;
packet.playerinfo.playerID = playerID;
packet.playerinfo.playerLocation = fromPlayer->m_playerLocation;
G_Lobby->SendPacketToLobbyAll(&packet);
}
}
else
{
//不是最后一个退出
if (room->m_chiefPlayerID == playerID)
{
//房主退出,变更房主
room->AutoChief();
S2CPacketRoomUpdate packet;
packet.roomID = room->m_roomID;
packet.chiefID = room->m_chiefPlayerID;
packet.roomType = room->m_roomType;
strcpy(packet.roomName,room->m_roomName);
room->SendPacketToRoomAll(&packet);
}
{
//通知当事人
S2CPacketExitRoom packet;
packet.m_res = 0;
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
}
{
//通知房间内其它玩家
S2CPacketOtherExitRoom packet;
packet.m_res = 0;
packet.roomID = roomID;
packet.playerID = playerID;
//strcpy(packet.roomName,roomName);
room->SendPacketToRoomOther(&packet,fromPlayer);
}
{
//通知大厅内其它玩家房间列表改变
S2CPacketRoomListUpdate packet;
packet.updateType = S2CPacketRoomListUpdate::Room_UpdateMember;
packet.roominfo.roomID = roomID;
G_Lobby->SendPacketToLobbyAll(&packet);
}
{
fromPlayer->m_roomID = -1;
fromPlayer->m_playerLocation = PL_INLOBBY;
//玩家列表改变
S2CPacketPlayerListUpdate packet;
packet.updateType = S2CPacketPlayerListUpdate::Player_UpdateLocation;
packet.playerinfo.playerID = playerID;
packet.playerinfo.playerLocation = fromPlayer->m_playerLocation;
G_Lobby->SendPacketToLobbyAll(&packet);
}
}
}
return true;
}
//==================^_^==================^_^==================^_^==================^_^
bool C2SPacketKickOtherRoomPlayer::Process()
{
可能是真人或ai, ai只存在于房间列表
//assert player->m_roomID == roomID
NetRoom* room = G_Lobby->GetRoom(roomID);
NetPlayer* fromPlayer = G_Lobby->GetPlayerBySocket(m_fromSocket);
if(room==NULL)
{
S2CPacketExitRoom packet;
packet.m_res = S2CPacketExitRoom::Err_NoRoom;//房间不存在
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketExitRoom房间不存在。\n",roomID);
return false;
}
//不是房主没有权限
if(room->m_chiefPlayerID!=fromPlayer->ObjID())
{
// S2CPacketKickOtherRoomPlayer packet;
// packet.m_res = S2CPacketKickOtherRoomPlayer::Err_NotChief;
// G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketKickOtherRoomPlayer不是房主没有权限。\n",roomID);
return false;
}
//真人或ai
NetPlayer* beKickPlayer = room->GetPlayerByID(playerID);
if(beKickPlayer==NULL)
{
S2CPacketExitRoom packet;
packet.m_res = S2CPacketExitRoom::Err_NotInRoom;//不在房间内
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketExitRoom玩家不存在。\n",playerID);
return false;
}
bool bAi = beKickPlayer->m_bAi;
int res = room->RemovePlayer(playerID);
if (res!=0)
{
S2CPacketExitRoom packet;
packet.m_res = S2CPacketExitRoom::Err_NotInRoom;//不在房间内
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketExitRoom不在房间内。\n",playerID);
return false;
}
else
{
//房主最后踢了房主
if(room->GetRealPlayerNum()==0)
{
//最后一个退出,解散房间
G_Lobby->RemoveRoom(roomID);
{
//通知被踢玩家
S2CPacketExitRoom packet;
packet.m_res = 0;
//strcpy(packet.roomName,roomName);
G_Server->SendPacketToSocket(&packet,beKickPlayer->m_socket);
}
{
//通知大厅内其它玩家房间列表改变
S2CPacketRoomListUpdate packet;
packet.updateType = S2CPacketRoomListUpdate::Room_Remove;
packet.roominfo.roomID = roomID;
G_Lobby->SendPacketToLobbyAll(&packet);
}
{
beKickPlayer->m_roomID = -1;
beKickPlayer->m_playerLocation = PL_INLOBBY;
//玩家列表改变
S2CPacketPlayerListUpdate packet;
packet.updateType = S2CPacketPlayerListUpdate::Player_UpdateLocation;
packet.playerinfo.playerID = playerID;
packet.playerinfo.playerLocation = beKickPlayer->m_playerLocation;
G_Lobby->SendPacketToLobbyAll(&packet);
}
}
else
{
//房主踢了房主
if (room->m_chiefPlayerID == playerID)
{
//房主退出,变更房主
room->AutoChief();
S2CPacketRoomUpdate packet;
packet.roomID = room->m_roomID;
packet.chiefID = room->m_chiefPlayerID;
packet.roomType = room->m_roomType;
strcpy(packet.roomName,room->m_roomName);
room->SendPacketToRoomAll(&packet);
}
if(bAi)
{
//通知房间内所有玩家
S2CPacketOtherExitRoom packet;
packet.m_res = 0;
packet.roomID = roomID;
packet.playerID = playerID;
//strcpy(packet.roomName,roomName);
room->SendPacketToRoomAll(&packet);
}
else
{
{
//通知被踢玩家
S2CPacketExitRoom packet;
packet.m_res = 0;
//strcpy(packet.roomName,roomName);
G_Server->SendPacketToSocket(&packet,beKickPlayer->m_socket);
}
{
//通知被踢除外的玩家
S2CPacketOtherExitRoom packet;
packet.m_res = 0;
packet.roomID = roomID;
packet.playerID = beKickPlayer->ObjID();
//strcpy(packet.roomName,roomName);
room->SendPacketToRoomOther(&packet,beKickPlayer);
}
}
{
//通知大厅内其它玩家房间列表改变
S2CPacketRoomListUpdate packet;
packet.updateType = S2CPacketRoomListUpdate::Room_UpdateMember;
packet.roominfo.roomID = roomID;
G_Lobby->SendPacketToLobbyAll(&packet);
}
if(bAi==false)
{
beKickPlayer->m_roomID = -1;
beKickPlayer->m_playerLocation = PL_INLOBBY;
//玩家列表改变
S2CPacketPlayerListUpdate packet;
packet.updateType = S2CPacketPlayerListUpdate::Player_UpdateLocation;
packet.playerinfo.playerID = playerID;
packet.playerinfo.playerLocation = beKickPlayer->m_playerLocation;
G_Lobby->SendPacketToLobbyAll(&packet);
}
}
}
return true;
}
bool C2SPacketRoomUpdate::Process()
{
NetPlayer* fromPlayer = G_Lobby->GetPlayerBySocket(m_fromSocket);
if(fromPlayer==NULL)
return false;
NetRoom* room = G_Lobby->GetRoom(roomID);
if(room==NULL)
{
S2CPacketExitRoom packet;
packet.m_res = S2CPacketEnterRoom::Err_NoRoom;//房间不存在
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
G_Server->LogSub("[%d] C2SPacketRoomUpdate房间不存在。\n",roomID);
return false;
}
if(room->m_chiefPlayerID!=fromPlayer->ObjID())
{
//不是房主 没有权限
S2CPacketRoomUpdate packet;
packet.m_res = -1;
room->SendPacketToRoomAll(&packet);
}
else
{
//房主退出,变更房主
room->m_chiefPlayerID = chiefID;
room->m_roomType = (MiniGameRoomType)roomType;
strcpy(room->m_roomName,roomName);
S2CPacketRoomUpdate packet;
packet.roomID = room->m_roomID;
packet.chiefID = room->m_chiefPlayerID;
packet.roomType = room->m_roomType;
strcpy(packet.roomName,room->m_roomName);
room->SendPacketToRoomAll(&packet);
{
//通知大厅内其它玩家房间列表改变
S2CPacketRoomListUpdate packet;
packet.updateType = S2CPacketRoomListUpdate::Room_Update;
packet.roominfo.roomID = roomID;
packet.roominfo.roomType = room->m_roomType;
packet.roominfo.ownerID = room->m_chiefPlayerID;
strcpy(packet.roominfo.roomName,room->m_roomName);
G_Lobby->SendPacketToLobbyAll(&packet);
}
}
return true;
}
//==================^_^==================^_^==================^_^==================^_^
bool C2SPacketRoomPlayerUpdate::Process()
{
NetPlayer* fromPlayer = G_Lobby->GetPlayerBySocket(m_fromSocket);
if(fromPlayer==NULL)
return false;
int roomID = fromPlayer->m_roomID;
NetRoom* room = G_Lobby->GetRoom(roomID);
if(room==NULL)
{
S2CPacketExitRoom packet;
packet.m_res = S2CPacketEnterRoom::Err_NoRoom;//房间不存在
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
// G_Server->LogSub("[%d] C2SPacketRoomUpdate房间不存在。\n",roomID);
return false;
}
if (updateType == RoomPlayer_AvatarChange)
{
//不会收到此类型,会收到weapon update
}
else if (updateType == RoomPlayer_SlotChange)
{
S2CPacketRoomPlayerUpdate packet;
packet.updateType = updateType;
//房主可以变更其它人的位置
NetPlayer* changePlayer = G_Lobby->GetPlayerByID(playerID);
NetPlayer* beChangePlayer = room->GetPlayerBySlot(toRoomSlot);
if(changePlayer==NULL)
{
// packet.m_res = S2CPacketRoomPlayerUpdate::Err_NoPL;
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
return false;
}
else if (room->m_chiefPlayerID!=fromPlayer->ObjID()
&&(changePlayer!=fromPlayer || beChangePlayer!=NULL)
)
{
//不是房主 没有权限
packet.m_res = -1;
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
return false;
}
else
{
//成功换队
if (beChangePlayer)
{
Swap(changePlayer->m_roomSlot,beChangePlayer->m_roomSlot);
packet.playerID = beChangePlayer->ObjID();
packet.toRoomSlot = beChangePlayer->m_roomSlot;
room->SendPacketToRoomAll(&packet);
}
else
{
changePlayer->m_roomSlot = toRoomSlot;
}
packet.m_res = 0;
packet.playerID = changePlayer->ObjID();
packet.toRoomSlot = changePlayer->m_roomSlot;
room->SendPacketToRoomAll(&packet);
{
//通知大厅内其它玩家房间列表改变
S2CPacketRoomListUpdate packet;
packet.updateType = S2CPacketRoomListUpdate::Room_Update;
packet.roominfo.roomID = roomID;
packet.roominfo.roomType = room->m_roomType;
packet.roominfo.ownerID = room->m_chiefPlayerID;
strcpy(packet.roominfo.roomName,room->m_roomName);
G_Lobby->SendPacketToLobbyAll(&packet);
}
}
}
else if (updateType == RoomPlayer_StyleChange)
{
S2CPacketRoomPlayerUpdate packet;
packet.updateType = updateType;
NetPlayer* changePlayer = G_Lobby->GetPlayerByID(playerID);
if(changePlayer==NULL)
{
// packet.m_res = S2CPacketRoomPlayerUpdate::Err_NoPL;
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
return false;
}
else
{
packet.miniPlayerStyle = miniPlayerStyle;
G_Lobby->SendPacketToPlayer(&packet,fromPlayer);
return false;
}
}
return true;
}
完