访问游戏对外服与扩展
介绍
访问游戏对外服与扩展,是框架提供的通讯方式之一,主要用于游戏逻辑服与游戏对外服的交互上。
本篇介绍如何从游戏对外服中获取我们需要的数据。
ExternalBizRegion 接口
ExternalBizRegion 接口是用于游戏对外服业务扩展,开发者通过实现这个接口,可以向游戏逻辑服提供一些,如
- 只存在于游戏对外服中的数据
- 只有游戏对外服可以做的事
框架通过这一扩展,轻松实现了如下功能;
- ExistUserExternalBizRegion 查询用户(玩家)是否在线,类似重复登录的检测
- ForcedOfflineExternalBizRegion 强制用户(玩家)下线,类似顶号的功能
- AttachmentExternalBizRegion 元附加信息
- 获取玩家 ip
如何扩展
实现 ExternalBizRegion 接口,并将编写好的实现类添加到 ExternalBizRegions 中
ExternalBizRegions.add(new YourExternalBizRegion());
示例
现在,我们通过一个示例来说明该接口的使用,该示例是从游戏对外服中获取在线玩家的 userId。
Example Source Code
see https://github.com/iohao/ioGameExamples
path : SimpleExample/example/example-external-biz-region
自定义 ExternalBizRegion 扩展类
OnlineUserExternalBizRegion 是 ExternalBizRegion 接口的扩展类。 类的内容比较简单,收集在线玩家的 userId。
public class OnlineUserExternalBizRegion implements ExternalBizRegion {
@Override
public int getBizCode() {
// custom business codes
// cn: 自定义业务码
return MyExternalBizCode.onlineUser;
}
@Override
public Serializable request(ExternalBizRegionContext regionContext) {
OnlineUser onlineUser = new OnlineUser();
regionContext.getUserSessions().forEach(userSession -> {
long userId = userSession.getUserId();
onlineUser.getUserIds().add(userId);
});
return onlineUser;
}
}
@Data
public class OnlineUser implements Serializable {
List<Long> userIds = new ArrayList<>();
}
public interface MyExternalBizCode {
int onlineUser = 1;
}
配置
将实现类添加到 ExternalBizRegions 中。
public class ExternalBizRegionApplication {
public static void main(String[] args) {
ExternalBizRegions.add(new OnlineUserExternalBizRegion());
...
}
}
使用
我们在 action 示例中触发 OnlineUserExternalBizRegion 相关逻辑。
- listOnlineUser 方法演示了访问玩家所在的【游戏对外服】
- listOnlineUserAll 方法演示了访问多个【游戏对外服】
@ActionController(ExternalBizRegionCmd.cmd)
public class ExternalBizRegionAction {
...
@ActionMethod(ExternalBizRegionCmd.listOnlineUser)
public List<Long> listOnlineUser(FlowContext flowContext) {
var collectExternalMessage = flowContext.invokeExternalModuleCollectMessage(MyExternalBizCode.onlineUser);
return listUserId(collectExternalMessage);
}
@ActionMethod(ExternalBizRegionCmd.listOnlineUserAll)
public List<Long> listOnlineUserAll(FlowContext flowContext) {
var request = flowContext.createRequestCollectExternalMessage(MyExternalBizCode.onlineUser);
var collectExternalMessage = flowContext.invokeExternalModuleCollectMessage(request);
return listUserId(collectExternalMessage);
}
static List<Long> listUserId(ResponseCollectExternalMessage collectExternalMessage) {
List<Long> userIdList = new ArrayList<>();
for (ResponseCollectExternalItemMessage itemMessage : collectExternalMessage.getMessageList()) {
// OnlineUserExternalBizRegion 所返回的数据
OnlineUser onlineUser = itemMessage.getData();
List<Long> userIds = onlineUser.getUserIds();
log.info("userIds : {}", userIds);
userIdList.addAll(userIds);
}
return userIdList;
}
}
小结
只要想象力足够,通过 ExternalBizRegion 接口可以做很多事。
通过扩展 ExternalBizRegion 接口,可以获取游戏对外服中的任何数据, flowContext.invokeExternalModuleCollectMessage 方法会向所有的游戏对外服发起请求。
在调用端的使用很简单,通过通讯上下文就可以调用了, 更多使用示例可以参考工具类 ExternalCommunicationKit。
如果游戏对外服、broker(游戏网关)、游戏逻辑服是分开部署的, 需要在 pom 中分别引入这个自定义的扩展类,因为 Serializable 会涉及到几个服务器之间的传输。
扩展阅读
访问指定的游戏对外服
默认情况下,广播会给所有的游戏对外服发送消息,因为我们的架构是支持启动多个游戏对外服的,你也可以手动设置需要访问的游戏对外服。
...
var requestCollectExternalMessage = new RequestCollectExternalMessage()
.setBizCode(yourExternalBizCode)
.setSourceClientId(sourceClientId);
BrokerClientHelper
.getInvokeExternalModuleContext()
.invokeExternalModuleCollectMessage(requestCollectExternalMessage);