Lobby2Client_360概览
带有Live的RakNet接口,包括音频聊天
XBOX没有提供房间和大厅的概念,事实上还是要求用户实现网络通讯来配置游戏比赛。RakNet使用Lobby2Client_360插件来处理这个问题。XBOX也不处理主机迁移,然而,如果如果加入了FullyConnectedMesh2插件,Lobby2Client_360插件可以自动检测主机迁移,自动执行适当的调用。参考例子代码,打开RakNet_360_VS2008.sln工程,然后运行LiveTest工程。
使用:
在LiveTest.cpp中的main()方法中,实例化Lobby2Client_360类,将它附加到RakPeer实例上。如果游戏比赛是端到端形式,想要实现主机迁移,则还需要附加上FullyConnectedMesh2插件。如果想要实现语音聊天,那么需要附带上RakVoiceXBOX360插件,同时要在SocketLayer.cpp中定义要使用的处理器标记RAKNET_USE_VDP。
创建房间:
发送Console_CreateRoom_360消息来创建房间。可以同时创建多个房间。房间是与XBOX控制台相关联的-但是,当创建房间时,房间里面没有任何用户。要向房间内加入用户,需要发送Console_SignIntoRoom_360消息。用户注册并进入房间有一些限制 – 例如,如果房间使用分类会话,那么来宾无法进入房间。
重要:由于在Live API中的设计缺陷,不可能结束并且重新开始分类会话。分类会话必须被销毁,并且重新创建。然而,这样会造成所有在会话中的用户掉线。因此,没有很好的方法保证用户在会话中永远没有重大错误地存在。
RakNet通过创建两个会话来解决这个问题(即使不使用分类会话也创建两个)。第一个在XBOX中的术语中通常被称为当前会话,这种叫法仅仅用于连接。只要在房间内,当前连接就一直持续存在,并不分类或公然断开(XSESSION_CREATE_USES_ARBITRATION)。即使合适的游戏模式是分类的,当前会话也不是分类的。
当前会话可以通过搜索返回,这样你可以连接到其他的控制台程序。然而,这样做会有两个问题:
1. 你不知道对应的游戏会话是不是分类的。
2. 当创建房间时,你必须从定义STANDARD的.xlast文件中指定标记。
解决第一个问题,你需要在.xlast文件中加入一个额外的标记,通常是当前会话的搜索属性,表明游戏房间是不是分类的。
.xlast文件是预定义了你想要运行的那种搜索,游戏的模式,语言和其他一些信息的文件。PS3都是通过编程实现的。例如,生成一个新的比赛生成查询,打开.xlast文件,打开”Xbox 360 and Live authoring submission tool”,打开.xlast文件,右击,然后点击新的matchmaking查询。
加入房间
首先,使用Console_SearchRooms_360消息搜索房间。XSENSSION_INFO成员是一个包含了要加入房间的信息的结构体,在房间列表的Console_SearchRooms_360::rooms[index].sr->info中有此成员。接下来,执行Console_JoinRoom_360,复制XSESSION_INFO到结构体的roomToJoin成员。如果Console_JoinRoom成功完成,房间的一个本地复制就创建了,NAT穿透也完成了。现在就可以从会话ID中获得远端系统的IP地址,会话ID是XSESSION_INFO的XNKID成员,可以在此成员使用SystemAddress::SetFromXSessionInfo。
如下是抽取IP地址,调用Connect()的代码:
SystemAddress roomToJoinAddress;
// 端口地址必须事先知道,它从XNKID返回回来。
roomToJoinAddress.SetFromXSessionInfo(&msg360->roomToJoin, RAKNET_PORT);
char ipAddress[32];
roomToJoinAddress.ToString(false, ipAddress);
rakPeer->Connect(ipAddress, roomToJoinAddress.port, ...);
注意此处仍然需要调用Console_SignIntoRoom_360来加入房间,就和你使用Console_CreateRoom_360一样简单。
主机迁移:
当创建房间的时候,你可以选择当房间主人离开时销毁房间,或迁移到其他主人(主机上),就是Console_CreateRoom_360中的supportHostMIgration成员。如果选择迁移主机,则要求加入FullyConnectedMesh2插件实现自动迁移主机。当然了XBOX提供了确定新的主机会话的方法,我们建议使用FullyConnectedMesh2,因为它与Lobby2Client_360集成,并且它跨平台。
当FullyConnectedMesh2检测到连接丢失,它会返回ID_FCM2_NEW_HOSt消息。这个消息被插件读取,所有的系统使用相同的host调用XSessionMigrateHost,透明地将房间host转移到一个新的系统上。当这些发生时,可以得到Notification_Console_RoomOwnerChanged回调函数。
语音:
RakVoiceXBOX360插件与RakNet集成,支持XBOX TCRs要求的IPPROTO_VDP,这个插件位于Samples\XBOX360\RakVoiceXBOX360。根绝TCRs,最开始的两个字节必须包含游戏数据的长度,剩下的数据包含的是语音数据。RakNet的结构不支持同时发送语音和游戏数据,例如RakPeer::Send()没有选项可以包含语音数据。
为了解决这个问题,对于普通的数据传输要求定义RAKNET_USE_VDP,这会将SocketLayer.cpp包含载荷长度作为每一个数据包的最开始两个字节。每一个数据报起始的两个字节被丢弃,因为载荷总是数据报的长度。
对于语音传输,插件RakVoiceXBOX360使用未编码的基带数据,直接调用SocketLayer::SnetTo_360函数。带外消息不会被RakPeer捕获,但是按照现有状况返回。插件会检查是否拦截这个带外数据。因为数据格式是提前知道的,插件不需要显示地告知载荷或语音数据的长度。任何没有读取的数据都当做语音数据对待,然后将数据传输给IXHV2Engine::SubmitIncommingChatData。
万一不清晰,不能简单调用SocketLayer::SendTo_360来传输语音和游戏数据。RakNet会丢弃没有有效格式的游戏数据,RakNet的游戏数据编码进了ReliabliityLayer.cpp。语音数据必须发送带外数据,就像插件实现的那样。