Closed iohao closed 7 months ago
使用参考
employHeadMetadata
方法会给模拟请求,即 RequestMessage headMetadata 添加上这些信息。employHeadMetadata
中所设置的数据(元信息、所绑定的游戏逻辑服)。@Slf4j
@RestController
@RequestMapping("other")
public class OtherController {
static final AtomicLong msgId = GameManagerController.msgId;
/** 为了方便测试,这里指定一个 userId 来模拟玩家 */
static final long userId = GameManagerController.userId;
@GetMapping("/notice")
public String notice() {
log.info("other notice");
// 使用协议碎片特性 https://www.yuque.com/iohao/game/ieimzn
StringValue data = StringValue.of("other GM web msg " + msgId.incrementAndGet());
// 模拟请求 : 路由 - 业务数据
RequestMessage requestMessage = BarMessageKit.createRequestMessage(ExchangeCmd.of(ExchangeCmd.notice), data);
// 设置需要模拟的玩家
HeadMetadata headMetadata = requestMessage.getHeadMetadata();
headMetadata.setUserId(userId);
// 从游戏对外服中获取一些用户(玩家的)自身的数据,如元信息、所绑定的游戏逻辑服 ...等
Optional<HeadMetadata> headMetadataOptional = ExternalCommunicationKit.employHeadMetadata(requestMessage);
if (headMetadataOptional.isPresent()) {
// 发起模拟请求
extractedRequestLogic(requestMessage);
// 打印从游戏对外服获取的元信息
byte[] attachmentData = headMetadata.getAttachmentData();
ExchangeAttachment attachment = DataCodecKit.decode(attachmentData, ExchangeAttachment.class);
return "other notice 玩家的元信息: %s - %s".formatted(attachment, msgId.get());
} else {
return "other notice 玩家 %s 不在线,无法获取玩家的元信息 - %s".formatted(userId, msgId.get());
}
}
private void extractedRequestLogic(RequestMessage requestMessage) {
// 向逻辑服发送请求,该模拟请求具备了玩家的元信息。
BrokerClient brokerClient = MyKit.brokerClient;
InvokeModuleContext invokeModuleContext = brokerClient.getInvokeModuleContext();
invokeModuleContext.invokeModuleVoidMessage(requestMessage);
}
}
下面是其他游戏逻辑服提供的 action,我们的模拟请求将会访问这个 action,在 code 12 ~ 13 获取并打印了元信息。
@Slf4j
@ActionController(ExchangeCmd.cmd)
public class ExchangeAction {
... 省略部分代码
@ActionMethod(ExchangeCmd.notice)
public void internalNotice(String msg, FlowContext flowContext) {
log.info("通过 GM 后台发送一条消息给玩家 [{}] - 消息内容 [{}]", flowContext.getUserId(), msg);
// 广播消息给玩家
// 使用协议碎片特性 https://www.yuque.com/iohao/game/ieimzn
flowContext.broadcastMe(StringValue.of(msg));
ExchangeAttachment attachment = flowContext.getAttachment(ExchangeAttachment.class);
log.info("attachment : {}", attachment);
}
}
小结
总体来说比较简单,关键代码只有一行
Optional
headMetadataOptional = ExternalCommunicationKit.employHeadMetadata(requestMessage);
为模拟请求附加上玩家所在游戏对外服中与自身相关的一些信息。
目前 employHeadMetadata
方法中只为模拟请求添加了元信息、所绑定的游戏逻辑服。此外,headMetadataOptional 中还包括了一些其他的信息,如有需要的可从中获取。参考代码如下
headMetadataOptional.ifPresent(externalHeadMetadata -> {
// 将用户元信息、所绑定的游戏逻辑服设置到 RequestMessage headMetadata 中
HeadMetadata headMetadata = requestMessage.getHeadMetadata();
headMetadata.setBindingLogicServerIds(externalHeadMetadata.getBindingLogicServerIds());
headMetadata.setAttachmentData(externalHeadMetadata.getAttachmentData());
... ...
});
新增功能的使用场景
从用户(玩家)所在游戏对外服中获取用户自身的数据,如用户所绑定的游戏逻辑服、元信息 ...等。
可用于模拟玩家请求。
使用场景
在模拟玩家请求时,有时需要用到玩家的元信息、已绑定游戏逻辑服 ...等相关信息。
通常,我们会在 GM 后台中模拟的玩家请求,但玩家的元信息、已绑定游戏逻辑服 ...等相关信息是无法知道的。那么就需要扩展 ExternalBizRegion 接口,从游戏对外服中获取相关数据。参考 获取游戏对外服的数据与扩展 (yuque.com)
其他参考:GM 后台与逻辑服交互 (yuque.com),模拟玩家的请求来访问 ioGame 其他逻辑服。
建议
如果业务的场景不复杂(也就是不需要玩家元信息、已绑定游戏逻辑服...等相关信息时),建议使用常规的方式来模拟玩家请求(常规的跨服调用)。
在实际中,使用常规的模拟玩家请求就能满足大部分业务场景的需求了。