HotFix.LandlordsLoginComponent学习笔记
请大家关注我的微博:@NormanLin_BadPixel坏像素
通过这个代码,我们终于开始接触具体怎么运用ET框架来运行游戏逻辑了。
我们需要在添加这个组件的时候,在Awake方法里进行初始化,所以我们需要订阅Awake事件,这样当我们在AddComponent的时候,就会调用Awake方法。怎么订阅呢?
[ObjectSystem]//需要有ObjectSystem特性
public class LandlordsLoginComponentAwakeSystem : AwakeSystem<LandlordsLoginComponent>
//继承相对应的抽象类,泛型里传入需要订阅事件的组件
{
public override void Awake(LandlordsLoginComponent self)
{
self.Awake();//调用具体的方法。
}
}
LandlordsLoginComponent.Awake方法里面很简单,作者注释的很详细了,这里讲一下,在初始话的时候给相应的按钮添加了点击事件,OnLogin跟OnRegister。这就是我们需要重点看的。
我们之前看了一堆消息调用,消息打包等知识,终于,让我们看到了这一切的起点!如何发起一个连接,我们学的东西终于有用了!
我们先看注册吧。
首先,我们需要跟服务器建立一个链接。
//创建登录服务器连接
IPEndPoint connetRealmEndPoint = NetworkHelper.ToIPEndPoint(GlobalConfigComponent.Instance.GlobalProto.Address);
session = Hotfix.Scene.ModelScene.GetComponent<NetOuterComponent>().Create(connetRealmEndPoint);
经过上面这一步,我们获取到了跟服务器的一个回话信息Session。之后,我们就可以通过这个Session发送信息和接收信息。
这里,我们需要发送一个注册请求并且接收服务器的回复。
//发送注册请求
prompt.text = "正在注册中....";
R2C_Register_Ack r2C_Register_Ack = await session.Call(new C2R_Register_Req() { Account = account.text, Password = password.text }) as R2C_Register_Ack;
需要注意的是,这里的session.Call是一个扩展方法,跟我们之前学的Session里面的Call方法是不同的,原来的Call方法传入的是Model层的IRequest,而在热更层,我们需要扩展一个新的方法,传入HotFix层的IRequest。
public static async Task<IResponse> Call(this Session session, IRequest request)
{
OpcodeTypeComponent opcodeTypeComponent = Hotfix.Scene.GetComponent<OpcodeTypeComponent>();
byte[] bytes = ProtobufHelper.ToBytes(request);
ushort opcode = opcodeTypeComponent.GetOpcode(request.GetType());
PacketInfo packetInfo = await session.Call(opcode, bytes);
ushort responseOpcode = packetInfo.Opcode;
Type t = opcodeTypeComponent.GetType(responseOpcode);
object aa = ProtobufHelper.FromBytes(t, packetInfo.Bytes, packetInfo.Index, packetInfo.Length);
IResponse response = (IResponse)aa;
return response;
}
我们来看看跟Model层的有什么区别。
有人会说对象的序列化跟反序列化不一样,其实我们仔细看一下
public Task<IResponse> Call(IRequest request)
...
byte[] bytes = this.Network.MessagePacker.SerializeToByteArray(request);
它是通过指定的打包工具进行序列化,其实demo默认的网络信息打包工具就是Protobuf,这里其实最后会调用的就是
ProtobufHelper.ToBytes(request);
这里可能写成
byte[] bytes = session.Network.MessagePacker.SerializeToByteArray(request);
会保险一点。(纯属个人瞎猜,是否正确?),反序列化也一样。
之后,我们通过获得热更信息的opcode跟byte[],通过session.Call(opcode, bytes) 来获取请求的返回信息包。这个方法是通用的。
同样的,我们需要返回的是热更层的IResponse。
我们来看看热更层的IRequest都有些什么。我们看到,基本上所有热更层的消息类都存放在HotfixMessage文件里。
通过大量的查阅,我们总结出定义消息的结构。我直接在上面注释了。
//Message特性,并且指定opcode,opcode存放在HotfixOpcode类里面。这样才能会注册入opcodeComponent里面。
[Message(HotfixOpcode.C2R_Register_Req)]
//Protobuf-net的用法,说明这个类可以被Protobuf序列化和反序列化
[ProtoContract]
//partial这个关键字,大家可以自行百度。
//Partial是局部类型的意思。允许我们将一个类、结构或接口分成几个部分,分别实现在几个不同的.cs文件中。C#编译器在编译的时候仍会将各个部分的局部类型合并成一个完整的类
public partial class C2R_Register_Req: IRequest//必须实现IRequest接口,其实就是一个标识
{
//Protobuf-net的用法,说明这个属性会在对象被序列化和反序列化的时候被识别
//没有ProtoMember这个特性的属性不会被序列化和反序列化。
//IsRequired说明这个属性是必须有的,不能为null
[ProtoMember(1, IsRequired = true)]
public string Account;
[ProtoMember(2, IsRequired = true)]
public string Password;
}
之后我们定义自己的消息类的时候,就可以按照上面的结构来定义。
同样的,IResponse也存放在HotfixMessage文件里,结构跟IRequest差不多,大家自行理解。
当我们接收到服务器返回的结果后,如果注册成功,则进入OnLogin方法,我们来瞅瞅。(失败后的处理就不说了,很简单。)
看过注册,登陆就很简单了。同样的,建立与服务器的连接,发送登陆的请求,接收结果,然后根据返回的结果创建Gate服务器连接,什么是Gate服务器?之后我们讲服务器那边的代码的时候会说,马上就得去讲了。
SessionComponent只是存放了与Gate服务器连接。
后面的作者注释的很详细了,我就不赘述了。
之后会出现许多客户端与服务器进行通话的情况,我们现在只知道客户端是怎么处理消息的,怎么发送消息的,但是并不知道服务器是怎么处理,又是怎么回复的。就像我们的X插入墙上的一个洞,拔出来后我们知道结果是什么,但是我们不知道墙那头到底是什么。(呜~开火车了。)
所以,这里我们就要进入另外一个大世界了,Landlords服务端的学习笔记。
2018/4/18补充笔记
我们花了好多好多时间,大致是对服务端有了一定的了解了。也对注册和登陆消息的处理做了详细的跟踪,现在就来补充一下登陆成功后的一些操作。
//保存连接,之后所有请求将通过这个连接发送
SessionComponent sessionComponent = Game.Scene.AddComponent<SessionComponent>();
sessionComponent.Session = gateSession;
Log.Info("登录成功");
//保存本地玩家
User user = Model.ComponentFactory.CreateWithId<User, long>(g2C_LoginGate_Ack.PlayerID, g2C_LoginGate_Ack.UserID);
ClientComponent.Instance.LocalPlayer = user;
//跳转到大厅界面
Hotfix.Scene.GetComponent<UIComponent>().Create(UIType.LandlordsLobby);
Hotfix.Scene.GetComponent<UIComponent>().Remove(UIType.LandlordsLogin);
啊,作者注释的很详细了,根本不需要我讲。
结束语
真是一山更比一山高———————–Norman林