Skip to main content

访问游戏对外服与扩展

介绍

访问游戏对外服与扩展,是框架提供的通讯方式之一,主要用于游戏逻辑服与游戏对外服的交互上。

本篇介绍如何从游戏对外服中获取我们需要的数据。

ExternalBizRegion 接口

ExternalBizRegion 接口是用于游戏对外服业务扩展,开发者通过实现这个接口,可以向游戏逻辑服提供一些,如

  1. 只存在于游戏对外服中的数据
  2. 只有游戏对外服可以做的事

框架通过这一扩展,轻松实现了如下功能;

如何扩展

实现 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

warning

如果游戏对外服、broker(游戏网关)、游戏逻辑服是分开部署的, 需要在 pom 中分别引入这个自定义的扩展类,因为 Serializable 会涉及到几个服务器之间的传输。

扩展阅读

访问指定的游戏对外服

默认情况下,广播会给所有的游戏对外服发送消息,因为我们的架构是支持启动多个游戏对外服的,你也可以手动设置需要访问的游戏对外服。

...

var requestCollectExternalMessage = new RequestCollectExternalMessage()
.setBizCode(yourExternalBizCode)
.setSourceClientId(sourceClientId);

BrokerClientHelper
.getInvokeExternalModuleContext()
.invokeExternalModuleCollectMessage(requestCollectExternalMessage);