Releases: iohao/ioGame
ioGame 21.20 netty 分布式网络游戏服务器框架,真轻量级网络编程框架
Documentation and Logs
Releases: 1 to 2 versions are released every month, and upgrades within a major version are always compatible, such as 21.1 is upgraded to any higher version 21.x
Version update summary
- feat(GenerateDoc): Add DocumentMethod annotation : Action supports generating documentation method names through annotations.
- BroadcastDebug enhancements.
- feat(GenerateCode): #328 Added C# code generation CsharpDocumentGenerate, which can generate interactive code for Unity and Godot.
feat(GenerateDoc): Add DocumentMethod annotation : Action supports generating documentation method names through annotations.
By default, the method names in the generated action interaction code use the method names from the Java action. The action can add the DocumentMethod
annotation to fix the method name, and when generating the integration code, ioGame will prioritize using the value of the DocumentMethod
annotation.
@ActionController(SdkCmd.cmd)
public final class SdkAction {
@ActionMethod(SdkCmd.noReturn)
@DocumentMethod("noReturnMethod")
public void noReturn(String name) {
... ...
}
}
feat(GenerateCode): #328 Added C# code generation CsharpDocumentGenerate, which can generate interactive code for Unity and Godot.
About examples
- see https://github.com/iohao/ioGameExamples/tree/main/SdkExample
- UnityExample: https://github.com/iohao/ioGameSdkCsharpExampleUnity
- GodotExample: https://github.com/iohao/ioGameSdkCsharpExampleGodot
public final class GenerateTest {
// setting root path
static String rootPath = "/Users/join/gitme/ioGame-sdk/";
public static void main(String[] args) {
// CHINA or US
Locale.setDefault(Locale.CHINA);
// Load the business framework of each gameLogicServer
// 加载游戏逻辑服的业务框架
yourListLogic().forEach(BrokerClientStartup::createBarSkeleton);
/*
* Generate actions, broadcasts, and error codes.
* cn: 生成 action、广播、错误码
*/
// About generating C# code
generateCodeCsharpGodot();
generateCodeCsharpUnity();
// Added an enumeration error code class to generate error code related information
IoGameDocumentHelper.addErrorCodeClass(YourGameCodeEnum.class);
// Generate document
IoGameDocumentHelper.generateDocument();
}
private static void generateCodeCsharpUnity() {
var documentGenerate = new CsharpDocumentGenerate();
// 设置代码生成所存放的路径,如果不做任何设置,将会生成在 target/code 目录中
// By default, it will be generated in the target/code directory
String path = rootPath + "ioGameSdkCsharpExampleUnity/Assets/Scripts/Gen/Code";
documentGenerate.setPath(path);
IoGameDocumentHelper.addDocumentGenerate(documentGenerate);
}
private static void generateCodeCsharpGodot() {
var documentGenerate = new CsharpDocumentGenerate();
// 设置代码生成所存放的路径,如果不做任何设置,将会生成在 target/code 目录中
// By default, it will be generated in the target/code directory
String path = rootPath + "ioGameSdkCsharpExampleGodot/script/gen/code";
documentGenerate.setPath(path);
IoGameDocumentHelper.addDocumentGenerate(documentGenerate);
}
}
Advantages of SDK Code Generation
- Helps client-side developers reduce significant workload by eliminating the need to write a large amount of template code.
- Clear and semantically precise. The generated interaction code clearly defines parameter types and return types.
- Ensures parameter type safety and clarity in interface methods, effectively avoiding security risks and reducing basic errors during integration.
- Reduces communication costs between the server and client during integration; the code serves as documentation. The generated integration code includes documentation and usage examples, and the examples on the methods will guide you on how to use them, making it zero-learning-cost even for beginners.
- Helps client-side developers abstract away the interaction with the server, allowing them to focus more on the core business logic.
- Reduces the cognitive load during integration. The code is simple to use, similar to local method calls.
- Abandons the traditional protocol-based approach in favor of an interface-method-based integration approach.
[other updates]
<protobuf-java.version>3.25.5</protobuf-java.version>
ioGame 21.19 netty 分布式网络游戏服务器框架,真轻量级网络编程框架
Documentation and Logs
Releases: 1 to 2 versions are released every month, and upgrades within a major version are always compatible, such as 21.1 is upgraded to any higher version 21.x
Version update summary
- [core] FlowContext provides the setUserId method to simplify the login operation.
- [broker] Added RingElementSelector load balancing implementation and set it as default to replace RandomElementSelector
- [core] #386 Action supports constructor injection with parameters in Spring
- Simplify the implementation class of ActionParserListener related to ProtoDataCodec. and #386
- perf(i18n): 🐳 #376 cmd check tips
- refactor(external): simplify and improve externalCache
[core] FlowContext provides the setUserId method to simplify the login operation.
@ActionController(LoginCmd.cmd)
public class TheLoginAction {
... ...
@ActionMethod(LoginCmd.login)
public UserInfo loginVerify(LoginVerify loginVerify, FlowContext flowContext) {
long userId = ...;
// Deprecated
boolean success = UserIdSettingKit.settingUserId(flowContext, userId);
// now
boolean success = flowContext.setUserId(userId);
return ...;
}
}
[core] #386 Action supports constructor injection with parameters in Spring
// Action supports constructor injection in Spring.
@Component
@AllArgsConstructor
@ActionController(PersonCmd.cmd)
public class PersonAction {
final PersonService personService;
...
}
refactor(external): simplify and improve externalCache
// create externalCache
private static void extractedExternalCache() {
// Deprecated
DefaultExternalCmdCache externalCmdCache = new DefaultExternalCmdCache();
// now
var externalCmdCache = ExternalCmdCache.of();
}
[other updates]
<netty.version>4.1.114.Final</netty.version>
ioGame 21.18 netty 分布式网络游戏服务器框架,真轻量级网络编程框架
文档与日志
- ioGame javadoc api
- 框架版本更新日志 (yuque.com) - ioGame update logs
- ioGame 真.轻量级网络编程框架 - 在线使用文档 - User Manual
ioGame 每月会发 1 ~ 2 个版本,通常在大版本内升级总是兼容的,如 21.1 升级到任意 21.x 的高版本。
Releases: 1 to 2 versions are released every month, and upgrades within a major version are always compatible, such as 21.1 is upgraded to any higher version 21.x
版本更新汇总
[core]
#376 Support i18n, such as logs and internal messages. 框架内的日志、内部消息支持 i18n。
public class DemoApplication {
public static void main(String[] args) {
// setting defaultLocale, such as US or CHINA
Locale.setDefault(Locale.US);
Locale.setDefault(Locale.CHINA);
... start ioGame
}
}
[其他更新]
<scalecube.version>2.6.17</scalecube.version>
ioGame 21.17 netty 分布式网络游戏服务器框架,真轻量级网络编程框架
文档与日志
ioGame 每月会发 1 ~ 2 个版本,通常在大版本内升级总是兼容的,如 21.1 升级到任意 21.x 的高版本。
版本更新汇总
- [core] 简化 TraceIdSupplier 默认实现(全链路调用日志跟踪)
- [core] FlowContext 提供用户(玩家)所关联的用户线程执行器信息及虚拟线程执行器信息方法
[core]
FlowContext 提供用户(玩家)所关联的用户线程执行器信息及虚拟线程执行器信息方法
void testThreadExecutor(FlowContext flowContext) {
// 获取 - 用户(玩家)所关联的用户线程执行器信息及虚拟线程执行器信息
// 用户虚拟线程执行器信息
ThreadExecutor virtualThreadExecutor = flowContext.getVirtualThreadExecutor();
// 用户线程执行器信息
ThreadExecutor threadExecutor = flowContext.getThreadExecutor();
threadExecutor.execute(() -> {
log.info("execute");
});
threadExecutor.executeTry(() -> {
log.info("executeTry");
});
// get Executor
Executor executor = threadExecutor.executor();
}
netty 分布式网络游戏服务器框架,真轻量级网络编程框架 ioGame 21.16
文档与日志
ioGame 每月会发 1 ~ 2 个版本,通常在大版本内升级总是兼容的,如 21.1 升级到任意 21.x 的高版本。
版本更新汇总
- [kit] #291 增加轻量可控的延时任务
- [kit] 细分时间日期相关工具。
- [Archive] #363 light-redis-lock 相关模块
- [Archive] #364 light-timer-task 相关模块
- [core] 增加同一个 ActionController 相同的 action 方法名只允许存在一个的检测。
- [core] Banner 增加启动时的错误数量提示。
- [core] #365 支持对接文档生成时,可以根据路由访问权限来控制文档的生成
[kit]
#291 增加轻量可控的延时任务
for example
@Test
public void example() {
long timeMillis = System.currentTimeMillis();
DelayTask delayTask = DelayTaskKit.of(() -> {
long value = System.currentTimeMillis() - timeMillis;
log.info("1 - 最终 {} ms 后,执行延时任务", value);
})
.plusTime(Duration.ofSeconds(1)) // 增加 1 秒的延时
.task(); // 启动任务
delayTask.plusTimeMillis(500); // 增加 0.5 秒的延时
delayTask.minusTimeMillis(500);// 减少 0.5 秒的延时时间
// 因为 taskId 相同,所以会覆盖之前的延时任务
String taskId = delayTask.getTaskId();
delayTask = DelayTaskKit.of(taskId, () -> {
long value = System.currentTimeMillis() - timeMillis;
log.info("2 - 最终 {} ms 后,执行延时任务", value);
})
.plusTime(Duration.ofSeconds(1)) // 增加 1 秒的延时
.task(); // 启动任务
// 取消延时任务,下面两个方法是等价的
delayTask.cancel();
DelayTaskKit.cancel(taskId);
// 可以通过 taskId 查找该延时任务
Optional<DelayTask> optionalDelayTask = DelayTaskKit.optional(taskId);
if (optionalDelayTask.isPresent()) {
var delayTask = optionalDelayTask.get();
}
// 通过 taskId 查找延时任务,存在则执行给定逻辑
DelayTaskKit.ifPresent(taskId, delayTask -> {
delayTask.plusTimeMillis(500); // 增加 0.5 秒的延时时间
});
}
细分时间日期相关工具。
see com.iohao.game.common.kit.time
[Archive]
#363 light-redis-lock 相关模块
将 light-redis-lock、light-redis-lock-spring-boot-starter 模块做归档。
在过去的时间里,由于一直没有改动这些模块的相关内容,现决定将不再上传到 maven 库中,以节约公共资源。如果你使用了该模块的相关内容,请指定最后一个版本即可。如
<!-- https://mvnrepository.com/artifact/com.iohao.game/light-redis-lock -->
<dependency>
<groupId>com.iohao.game</groupId>
<artifactId>light-redis-lock</artifactId>
<version>21.15</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.iohao.game/light-redis-lock-spring-boot-starter -->
<dependency>
<groupId>com.iohao.game</groupId>
<artifactId>light-redis-lock-spring-boot-starter</artifactId>
<version>21.15</version>
</dependency>
模块相关文档 - redis-lock 分布式锁 (yuque.com)
#364 light-timer-task 相关模块
将 light-timer-task 模块做归档。
在过去的时间里,由于一直没有改动这些模块的相关内容;同时,也因为框架内置了类似的功能 #291 。现决定将不再上传到 maven 库中,以节约公共资源。如果你使用了该模块的相关内容,请指定最后一个版本即可。如
<!-- https://mvnrepository.com/artifact/com.iohao.game/light-timer-task -->
<dependency>
<groupId>com.iohao.game</groupId>
<artifactId>light-timer-task</artifactId>
<version>21.15</version>
</dependency>
模块相关文档 - timer-task 任务延时器 (yuque.com)
类似的代替 轻量可控的延时任务 (yuque.com)
[core]
#365 支持对接文档生成时,可以根据路由访问权限来控制文档的生成
生成相关代码的使用及相关文档
ExternalGlobalConfig.accessAuthenticationHook
,相关文档 - 路由访问权限控制 (yuque.com)- IoGameDocumentHelper,相关文档 - 游戏对接文档生成 (yuque.com)
for example
public class MyExternalServer {
public static void extractedAccess() {
// https://www.yuque.com/iohao/game/nap5y8p5fevhv99y
var accessAuthenticationHook = ExternalGlobalConfig.accessAuthenticationHook;
... 省略部分代码
// 添加 - 拒绝玩家访问权限的控制
accessAuthenticationHook.addRejectionCmd(RankCmd.cmd, RankCmd.internalUpdate);
}
}
public class TestGenerate {
... 省略部分代码
public static void main(String[] args) {
// 对外服访问权限控制
MyExternalServer.extractedAccess();
// (复用)设置文档路由访问权限控制
IoGameDocumentHelper.setDocumentAccessAuthentication(ExternalGlobalConfig.accessAuthenticationHook::reject);
// ====== 生成对接文档、生成 proto ======
// generateCsharp();
// generateTypeScript();
// 生成文档
IoGameDocumentHelper.generateDocument();
// .proto 文件生成
// generateProtoFile();
}
}
预览 - 没有做控制前的生成
==================== RankAction ====================
路由: 4 - 1 --- 【listRank】 --- 【RankAction:48】【listRank】
方法参数: StringValue 排行类型
方法返回值: ByteValueList<RankUpdate> 玩家排行名次更新
路由: 4 - 10 --- 【玩家排行名次更新】 --- 【RankAction:60】【internalUpdate】
方法参数: RankUpdate 玩家排行名次更新
方法返回值: void
预览 - 加入了访问控制后的生成
我们可以看见,路由为 4-10 的 action 方法没有生成到对接文档中。
==================== RankAction ====================
路由: 4 - 1 --- 【listRank】 --- 【RankAction:48】【listRank】
方法参数: StringValue 排行类型
方法返回值: ByteValueList<RankUpdate> 玩家排行名次更新
提示:除了文档文档的访问权限控制外,还支持 SDK TypeScript、SDK C# ...等客户端代码生成的访问权限控制。
SDK 相关请阅读:SDK&对接文档 (yuque.com)
[其他更新]
<netty.version>4.1.113.Final</netty.version>
netty 分布式网络游戏服务器框架 & 真轻量级网络编程框架 ioGame 21.15
文档与日志
通常在大版本内升级总是兼容的,如 21.1 升级到任意 21.x 的高版本。
ioGame 发版本的频率:每月会发 1 ~ 2 个版本。
版本更新汇总
- [core] #351 增加 UserProcessor 线程执行器的选择策略扩展
- [core] #350 修复请求消息在 Broker 环节乱序的问题
- [core] #353 对接文档支持框架内置错误码的生成
- [core] #354 日志打印调整
- [core] #359 [逻辑服-监听] 增加打印其他进程逻辑服的上线与下线信息
- [core] 优化 ThreadExecutorRegion 相关实现类。
- [external] UserSession 接口新增 ofRequestMessage 方法,简化玩家在游戏对外服中创建请求对象。
[external]
UserSession 接口新增 ofRequestMessage 方法,简化玩家在游戏对外服中创建请求对象。
for example
var cmdInfo = CmdInfo.of(1, 1);
RequestMessage request = userSession.ofRequestMessage(cmdInfo);
[core]
#359 [逻辑服-监听] 增加打印其他进程逻辑服的上线与下线信息
public class MyLogicServer extends AbstractBrokerClientStartup {
...
@Override
public BrokerClientBuilder createBrokerClientBuilder() {
BrokerClientBuilder builder = BrokerClient.newBuilder();
...
// 添加监听 - 打印其他进程逻辑服的上线与下线信息
builder.addListener(SimplePrintBrokerClientListener.me());
return builder;
}
}
#351 增加 UserProcessor 线程执行器的选择策略扩展
for example
// 为请求消息开启有序的、多线程处理的优化
IoGameGlobalConfig.enableUserProcessorExecutorSelector();
注意事项:当你的 UserProcessor 做了线程执行器的选择策略扩展,需要重写 CustomSerializer 接口的相关方法。
ioGame 21.14,netty 分布式游戏服务器框架;java 分步式游戏服务器框架;
ioGame 发版本的频率:每月会发 1 ~ 2 个版本。通常在大版本内升级总是兼容的,如 21.1 升级到任意 21.x 的高版本。
文档与日志
版本更新汇总
- [code quality] 提升代码质量
- [javadoc] 增强相关模块的 javadoc :业务框架、压测与模拟客户端请求、领域事件、Room
- [core] #346 业务框架 InOutManager 提供扩展点
- [core] #344 登录时,如果 FlowContext 存在 userId 就不请求游戏对外服
- [broker] fixed #342 非集群环境下,Broker 断开重启后,逻辑服没有将其重新加入到 BrokerClientManager 中所引发的 NPE。
[core]
#346 业务框架 InOutManager 提供扩展点
在构建器中配置 InOutManager 策略,框架内置了两个实现类,分别是
- ofAbcAbc :in ABC,out ABC 的顺序,即编排时的顺序。
- ofPipeline:in ABC,out CBA 的顺序,类似的 netty Pipeline 。(默认策略,如果不做任何设置,将使用该策略)
for example
在构建器中配置 InOutManager 策略
public void config() {
BarSkeletonBuilder builder = ...;
builder.setInOutManager(InOutManager.ofAbcAbc());
builder.setInOutManager(InOutManager.ofPipeline());
}
ioGame 21.13,netty 分布式游戏服务器框架;java 分步式游戏服务器框架;
文档与日志
版本更新汇总
- [external] #334 顶号操作 bug,有概率触发并发问题
- [core] FlowContext 新增 createRequestCollectExternalMessage 方法
- [javadoc] 源码 javadoc 增强
[core]
FlowContext 新增 createRequestCollectExternalMessage 方法,request 与游戏对外服交互。相关使用文档请阅读 获取游戏对外服的数据与扩展 (yuque.com)
... ... 省略部分代码
@ActionMethod(ExternalBizRegionCmd.listOnlineUserAll)
public List<Long> listOnlineUserAll(FlowContext flowContext) {
// 创建 RequestCollectExternalMessage
var request = flowContext
.createRequestCollectExternalMessage(MyExternalBizCode.onlineUser);
// 访问多个【游戏对外服】
var collectExternalMessage = flowContext
.invokeExternalModuleCollectMessage(request);
return listUserId(collectExternalMessage);
}
[其他更新]
<netty.version>4.1.112.Final</netty.version>
<lombok.version>1.18.34</lombok.version>
ioGame 21.12,netty 分布式游戏服务器框架;java 分步式游戏服务器框架;
文档与日志
版本更新汇总
- [light-game-room] #326 GameFlowContext getRoom、getPlayer 方法返回值改成泛型
- [对接文档] #330 增强,支持对接文档生成与扩展,包括文本文档生成、联调代码生成 ...等
[light-game-room]
#326 GameFlowContext getRoom、getPlayer 方法返回值改成泛型
GameFlowContext gameFlowContext = ...;
// FightRoomEntity、FightPlayerEntity 是自定义的 Room、Player 对象
// Room、Player 在使用时,不需要强制转换了
FightRoomEntity room = gameFlowContext.getRoom();
FightPlayerEntity player = gameFlowContext.getPlayer();
[对接文档]
#330 增强,支持对接文档生成与扩展,包括文本文档生成、联调代码生成 ...等。开发者做更多个性化的扩展
在该版本中,我们已经新做了对接文档相关模块;该版本功能更加的强大,使用上也更加的简洁。新版本的对接文档模块,除了能提供文本文档的生成外,还能支持生成与客户端联调的代码、并且是可扩展的。通常,客户端联调代码有:
- 支持生成 C# 客户端的联调代码,通常用在 Unity、Godot 客户端,具体可阅读 SDK C# 代码生成。
- 支持生成 TypeScript 客户端的联调代码,通常用在 cocos、laya 客户端,具体可阅读 SDK TypeScript 代码生成。
public static void main(String[] args) {
// 添加枚举错误码 class,用于生成错误码相关信息
IoGameDocumentHelper.addErrorCodeClass(GameCode.class);
// 添加文档生成器,文本文档
IoGameDocumentHelper.addDocumentGenerate(new TextDocumentGenerate());
// 添加文档生成器,Ts 联调代码生成
IoGameDocumentHelper.addDocumentGenerate(new TypeScriptDocumentGenerate());
// 生成文档
IoGameDocumentHelper.generateDocument();
}
上述代码
- 添加了错误码的生成
- 添加了文本文档的生成
- 添加了 Ts 客户端联调代码的生成(包括 action、广播、错误码...相关代码的生成), SDK TypeScript 客户端代码生成;方便 CocosCeator、或其他支持 TypeScript 的客户端对接。 #329
addDocumentGenerate 是可扩展的,这将意味着开发者可以扩展出 C#、GodotScript、Js ...等不同客户端的联调代码。默认,我们提供了一个文本文档,即 TextDocumentGenerate,如果默认的实现满足不了当下需求,开发者也可以定制个性化的文档,如 json 格式的。
更多内容请阅读 游戏对接文档生成 (yuque.com)
新增 DocumentGenerate 接口
开发者可利用该接口进行定制个性化的对接文档,如代码生成 ...等。
/**
* 对接文档生成接口,可扩展不同的实现
*/
public interface DocumentGenerate {
/**
* 生成文档
*
* @param ioGameDocument ioGameDocument
*/
void generate(IoGameDocument ioGameDocument);
}
/**
* 文档相关信息,如 action 相关、广播相关、错误码相关。
*/
@Getter
public final class IoGameDocument {
/** 已经解析好的广播文档 */
List<BroadcastDocument> broadcastDocumentList;
/** 已经解析好的错误码文档 */
List<ErrorCodeDocument> errorCodeDocumentList;
/** 已经解析好的 action 文档 */
List<ActionDoc> actionDocList;
}
开发者可以通过实现 DocumentGenerate 接口来扩展不同的文档生成,开发者可以扩展此接口来定制更多个性化的扩展,如
- html 版本的文档。
- json 版本的文档。
- 其他语言的联调文档 ...等。
// 使用示例
private static void test() {
var documentGenerate = new YourDocumentGenerate();
IoGameDocumentHelper.addDocumentGenerate(documentGenerate);
}
其他:废弃旧版本对接文档相关类 DocActionSend、DocActionSends、ActionDocs、ActionSendDoc、ActionSendDocs、ActionSendDocsRegion、BarSkeletonDoc、BroadcastDoc、BroadcastDocBuilder、ErrorCodeDocs、ErrorCodeDocsRegion。
21.10 及之前版本的使用示例(对接文档)
public static void main(String[] args) {
... 省略部分代码
new NettyRunOne()
... ...
.startup();
// 生成对接文档
BarSkeletonDoc.me().buildDoc();
}
ioGame 21.10,netty 分布式游戏服务器框架;java 分步式游戏服务器框架;
文档与日志
版本更新汇总
- [core] #315 ResponseMessage 增加协议碎片便捷获取,简化跨服调用时的使用
- [core] ActionCommand 增加 containAnnotation、getAnnotation 方法,简化获取 action 相关注解信息的使用。
- [kit] [动态属性] 增加 ifNull 方法,如果动态属性值为 null,则执行给定的操作,否则不执行任何操作。执行给定操作后将得到一个返回值,该返回值会设置到动态属性中。
- [kit] TimeKit 增加 nowLocalDate 方法,可减少 LocalDate 对象的创建;优化 currentTimeMillis 方法的时间更新策略。同时,优化 nowLocalDate、currentTimeMillis 方法,不使用时将不会占用相关资源。
- [EventBus] 分布式事件总线增加 EventBusRunner 接口。EventBus 接口化,方便开发者自定义扩展。fix 订阅者使用自身所关联的 EventBus 处理相关事件。
[core] 315 ResponseMessage 增加协议碎片便捷获取,简化跨服调用时的使用
框架具备协议碎片特性。某些业务中,我们需要跨服访问其他游戏逻辑服,以获取某些业务数据;一些简单的数据,我们可以通过协议碎片来返回,从而避免定义过多的协议。
现为 ResponseMessage 增加协议碎片支持,简化跨服调用时的使用,新增的方法如下
public void test() {
ResponseMessage responseMessage = ...;
// object
responseMessage.getValue(Student.class);
List<Student> listValue = responseMessage.listValue(Student.class);
// int
int intValue = responseMessage.getInt();
List<Integer> listInt = responseMessage.listInt();
// long
long longValue = responseMessage.getLong();
List<Long> listLong = responseMessage.listLong();
// String
String stringValue = responseMessage.getString();
List<String> listString = responseMessage.listString();
// boolean
boolean boolValue = responseMessage.getBoolean();
List<Boolean> listBoolean = responseMessage.listBoolean();
}
示例说明
- HomeAction 是 【Home 游戏逻辑服】提供的 action
- UserAction 是 【User 游戏逻辑服】提供的 action
两个逻辑服的交互如下,UserAction 使用跨服方式调用了【Home 游戏逻辑服】的几个方法,并通过 responseMessage 的协议碎片支持,简化跨服调用时的使用。
示例中演示了 string、string list、object list 的简化使用(协议碎片获取时的简化使用)。
@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
public class Student {
String name;
}
// home 游戏逻辑服提供的 action
public class HomeAction {
@ActionMethod(HomeCmd.name)
public String name() {
return "a";
}
@ActionMethod(HomeCmd.listName)
public List<String> listName() {
return List.of("a", "b");
}
@ActionMethod(HomeCmd.listStudent)
public List<Student> listStudent() {
Student student = new Student();
student.name = "a";
Student student2 = new Student();
student2.name = "b";
return List.of(student, student2);
}
}
@ActionController(UserCmd.cmd)
public class UserAction {
@ActionMethod(UserCmd.userSleep)
public void userSleep(FlowContext flowContext) {
flowContext.invokeModuleMessageAsync(HomeCmd.of(HomeCmd.name), responseMessage -> {
String name = responseMessage.getString();
log.info("{}", name);
});
flowContext.invokeModuleMessageAsync(HomeCmd.of(HomeCmd.listName), responseMessage -> {
var listName = responseMessage.listString();
log.info("{}", listName);
});
flowContext.invokeModuleMessageAsync(HomeCmd.of(HomeCmd.listStudent), responseMessage -> {
List<Student> studentList = responseMessage.listValue(Student.class);
log.info("{}", studentList);
});
}
}
[core] ActionCommand 增加 containAnnotation、getAnnotation 方法,简化获取 action 相关注解信息的使用。
ActionCommand actionCommand = flowContext.getActionCommand();
bool contain = actionCommand.containAnnotation(DisableDebugInout.class);
var annotation = actionCommand.getAnnotation(DisableDebugInout.class);
[EventBus] 分布式事件总线
- [增强扩展] 将抽象类 AbstractEventBusRunner 标记为过时的,由接口 EventBusRunner 代替。
- [增强扩展] 分布式事件总线 EventBus 接口化,方便开发者自定义扩展。增加总线相关的 javadoc。
- [fix] 订阅者使用自身所关联的 EventBus 处理相关事件。
关于 fix 订阅者使用自身所关联的 EventBus 处理相关事件,在此之前可能引发 bug 的场景如下
- 【游戏逻辑服 A】 发布事件。
- 【游戏逻辑服 B】 订阅者接收事件并处理,在处理过程中又调用了【游戏逻辑服 A】 某个 action 方法。
该业务场景,会在多服单进程下会引发调用超时,但在多服多进程下则不会超时。
[kit] TimeKit
增强 TimeKit 增加 nowLocalDate 方法,可减少 LocalDate 对象的创建;
优化 currentTimeMillis 方法的时间更新策略。
优化 nowLocalDate、currentTimeMillis 不使用时将不会占用相关资源。
@Test
public void test() {
long millis = TimeKit.currentTimeMillis();
Assert.assertTrue(millis > 0);
LocalDate localDate = TimeKit.nowLocalDate();
Assert.assertTrue(localDate.isEqual(LocalDate.now()));
}
[kit] 动态属性
[动态属性] 增加 ifNull 方法,如果动态属性值为 null,则执行给定的操作,否则不执行任何操作。执行给定操作后将得到一个返回值,该返回值会设置到动态属性中。
public class AttrOptionDynamicTest {
// 动态属性 key
AttrOption<AttrCat> attrCatOption = AttrOption.valueOf("AttrCat");
@Test
public void ifNull() {
var myAttrOptions = new MyAttrOptions();
Assert.assertNull(myAttrOptions.option(attrCatOption));
// 如果 catAttrOption 属性为 null,则创建 AttrCat 对象,并赋值到属性中
myAttrOptions.ifNull(attrCatOption, AttrCat::new);
Assert.assertNotNull(myAttrOptions.option(attrCatOption));
}
private static class AttrCat {
String name;
}
@Getter
private static class MyAttrOptions implements AttrOptionDynamic {
final AttrOptions options = new AttrOptions();
}
}
[其他 - 相关库升级]
<netty.version>4.1.111.Final</netty.version>
<jctools-core.version>4.0.5</jctools-core.version>
<jprotobuf.version>2.4.23</jprotobuf.version>