任务25:退出房间功能与网关user的ActorID
这节的效果是玩家可以匹配后进入房间等待三人齐备好开始游戏,等待中可以退出房间,再重新匹配进入房间。
前面学过,每当玩家进入地图,Map就给网关发送了Actor_MatchSucess_M2G消息,从而更新了网关user的ActorDI。
\Server\Hotfix\Landlords\Handler\Gate\M2G_MatchSucess_Handler.cs
//gate更新ActorID user.ActorID = message.GamerID;
这个GamerID正是Map通过消息传递过来的Map上gamer的InstanceId。
所以玩家到了哪个地图,就会在地图上创建gamer后,把gamer的InstanceId传送给网关存入网关上user的ActorDI。
这就意味着,不论玩家到了哪个地图,我们在任何一个端中,都可以通过网关用user.ActorID构建ActorMessageSender,给Map上的gamer发送消息。
服务端增加 C2G_ReturnLobby_Ntt_Handler
前端用户点退出房间按钮,向网关发送了这条消息 \Server\Hotfix\Landlords\Handler\Gate\C2G_ReturnLobby_NttHandler.cs
using ETModel; using System.Net; namespace ETHotfix { [MessageHandler(AppType.Gate)] public class C2G_ReturnLobby_NttHandler : AMHandler<C2G_ReturnLobby_Ntt> { protected override async ETTask Run(Session session, C2G_ReturnLobby_Ntt message) { //验证Session if (!GateHelper.SignSession(session)) { return; } User user = session.GetComponent<SessionUserComponent>().User; StartConfigComponent config = Game.Scene.GetComponent<StartConfigComponent>(); ActorMessageSenderComponent actorProxyComponent = Game.Scene.GetComponent<ActorMessageSenderComponent>(); //通知Map服务器玩家离开房间 if (user.ActorID != 0) { ActorMessageSender actorProxy = actorProxyComponent.Get(user.ActorID); actorProxy.Send(new Actor_PlayerExitRoom_G2M()); user.ActorID = 0; } await ETTask.CompletedTask; } } }
服务端增加 G2M_PlayerExitRoom_Handler
\Server\Hotfix\Landlords\Handler\Map\G2M_PlayerExitRoom_Handler.cs
using System; using System.Threading.Tasks; using ETModel; namespace ETHotfix { //Gate通知Map玩家退出房间 [ActorMessageHandler(AppType.Map)] public class G2M_PlayerExitRoom_Handler : AMActorHandler<Gamer, Actor_PlayerExitRoom_G2M> { protected override async ETTask Run(Gamer gamer, Actor_PlayerExitRoom_G2M message) { Room room; if (Game.Scene.GetComponent<LandMatchComponent>().Playing.TryGetValue(gamer.UserID,out room)) { gamer.isOffline = true; //玩家断开添加自动出牌组件 //... } else //玩家不在游戏中 处于待机状态 { Game.Scene.GetComponent<LandMatchComponent>().Waiting.TryGetValue(gamer.UserID,out room); //房间移除玩家 room.Remove(gamer.UserID); Game.Scene.GetComponent<LandMatchComponent>().Waiting.Remove(gamer.UserID); //消息广播给其他人 room.Broadcast(new Actor_GamerExitRoom_Ntt() { UserID = gamer.UserID }); gamer.Dispose(); } await ETTask.CompletedTask; } } }
InnerMessage.proto 增加Actor_PlayerExitRoom_G2M
//Gate通知Map玩家离开房间 message Actor_PlayerExitRoom_G2M // IActorMessage { int32 RpcId = 90; int64 ActorId = 94; }
前端增加Actor_GamerExitRoom_NttHandler
using ETModel; namespace ETModel { [MessageHandler] public class Actor_GamerExitRoom_NttHandler : AMHandler<Actor_GamerExitRoom_Ntt> { protected override async ETTask Run(ETModel.Session session, Actor_GamerExitRoom_Ntt message) { UI uiRoom = Game.Scene.GetComponent<UIComponent>().Get(LandUIType.LandRoom); LandRoomComponent landlordsRoomComponent = uiRoom.GetComponent<LandRoomComponent>(); landlordsRoomComponent.RemoveGamer(message.UserID); await ETTask.CompletedTask; } } }
最后就可以进行前后端运行测试了,可以看到后端的输出反馈