Skip to main content

玩家登录

介绍

本篇,我们将介绍玩家登录功能。学习完后,你将可以完成登录、顶号、禁止重复登录等功能。

登录

我们定义了两个数据协议 LoginVerifyUserInfo,用于处理登录业务。

  • code 10,flowContext.bindingUserId 方法是登录的关键代码, 目的是在对外服的 channel 中设置用户的真实 userId。 之后用户的每次请求,可以通过 FlowContext 来获取该玩家的相关信息, FlowContext 是玩家这一次请求的上下文。
@ActionController(1)
public class LoginAction {
@ActionMethod(1)
public UserInfo loginVerify(LoginVerify loginVerify, FlowContext flowContext) {
String jwt = loginVerify.jwt;

// get user by jwt
UserInfo userInfo = ...;
long userId = userInfo.id;
boolean success = flowContext.bindingUserId(userId);

if (!success) {
// assert code
...
}

return userInfo;
}
}

@ProtobufClass
public class LoginVerify {
public String jwt;
}

@ProtobufClass
public class UserInfo {
public long userId;
public String name;
}
warning

一定要调用框架提供的这个方法才算是用户验证成功,否则后续在 FlowContext 上下文中拿不到 userId。

禁止重复登录

禁止重复登录指的是相同的号已经在线上了,不能重复登录该账号了。 登录相关的代码,在综合示例中。

  • code 8,检测玩家是否在线。
  • code 9,断言+异常机制,如果玩家在线就返回错误码给请求端。
  • code 11,登录。
@ActionMethod(1)
public UserInfo loginVerify(LoginVerify loginVerify, FlowContext flowContext) {

// get user by jwt
UserInfo userInfo = ...
long userId = userInfo.id;

boolean existUser = ExternalCommunicationKit.existUser(userId);
GameCode.accountOnline.assertTrueThrows(existUser);

boolean success = flowContext.bindingUserId(userId);
...
return userInfo;
}

@Getter
public enum GameCode implements MsgExceptionInfo {
accountOnline(100, "User Online");

final int code;
final String msg;

GameCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
}

顶号

顶号指的是相同的号已经在线上了,把在线上的号顶下线,以最后一次登录为准。

  • code 8,强制指定玩家下线。
  • code 10,登录。
@ActionMethod(1)
public UserInfo loginVerify(LoginVerify loginVerify, FlowContext flowContext) {

// get user by jwt
UserInfo userInfo = ...
long userId = userInfo.id;

ExternalCommunicationKit.forcedOffline(userId);

boolean success = flowContext.bindingUserId(userId);
...

return userInfo;
}

UserId

登录后,可以通过 FlowContext 来获取玩家 userId。

@ActionMethod(2)
public long hello(FlowContext flowContext) {
return flowContext.getUserId();
}

userId 可以支持 String 类型的 Id 吗?

业务需求: 如果 userId 不是 long 类型的怎么办?我使用的是 MongoDB objectId 是 String 类型的。

ioGame 是一个扩展性极强的框架,这样的需求也是支持扩展的。扩展步骤如下

  1. 给用户数据关联一个 long 类型的 id,比如 Snowflake
  2. 将 objectId 存放到元信息-附加信息
  3. 配合自定义FlowContext
@ProtobufClass
public class MyAttachment implements Attachment {
@Getter
long userId;
/** MongoDB objectId */
public String objectId;
}

public class MyFlowContext extends FlowContext {
public String getUserIdString() {
var attachment = this.getAttachment(MyAttachment.class);
return attachment.objectId;
}
}