Skip to content

Releases: iohao/ioGame

ioGame 21.19 netty 分布式网络游戏服务器框架,真轻量级网络编程框架

28 Oct 01:40
Compare
Choose a tag to compare

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

  1. [core] FlowContext provides the setUserId method to simplify the login operation.
  2. [broker] Added RingElementSelector load balancing implementation and set it as default to replace RandomElementSelector
  3. [core] #386 Action supports constructor injection with parameters in Spring
  4. Simplify the implementation class of ActionParserListener related to ProtoDataCodec. and #386
  5. perf(i18n): 🐳 #376 cmd check tips
  6. 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 分布式网络游戏服务器框架,真轻量级网络编程框架

09 Oct 06:03
Compare
Choose a tag to compare

文档与日志

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


版本更新汇总

  • [external] #375 Support for lightweight or embedded Linux distributions. 支持轻量级或嵌入式 Linux 发行版。
  • [core] #376 Support i18n, such as logs and internal messages. 框架内的日志、内部消息支持 i18n。

[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 分布式网络游戏服务器框架,真轻量级网络编程框架

25 Sep 08:09
Compare
Choose a tag to compare

文档与日志

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

09 Sep 05:10
Compare
Choose a tag to compare

文档与日志

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 增加轻量可控的延时任务

文档 - 轻量可控的延时任务 (yuque.com)

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 支持对接文档生成时,可以根据路由访问权限来控制文档的生成

生成相关代码的使用及相关文档

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

26 Aug 05:07
Compare
Choose a tag to compare

文档与日志

通常在大版本内升级总是兼容的,如 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 分步式游戏服务器框架;

08 Aug 08:35
Compare
Choose a tag to compare

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 策略,框架内置了两个实现类,分别是

  1. ofAbcAbc :in ABC,out ABC 的顺序,即编排时的顺序。
  2. 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 分步式游戏服务器框架;

24 Jul 07:48
Compare
Choose a tag to compare

文档与日志


版本更新汇总

  • [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 分步式游戏服务器框架;

08 Jul 03:34
Compare
Choose a tag to compare

文档与日志


版本更新汇总

  • [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 增强,支持对接文档生成与扩展,包括文本文档生成、联调代码生成 ...等。开发者做更多个性化的扩展

在该版本中,我们已经新做了对接文档相关模块;该版本功能更加的强大,使用上也更加的简洁。新版本的对接文档模块,除了能提供文本文档的生成外,还能支持生成与客户端联调的代码、并且是可扩展的。通常,客户端联调代码有:

  1. 支持生成 C# 客户端的联调代码,通常用在 Unity、Godot 客户端,具体可阅读 SDK C# 代码生成
  2. 支持生成 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();
}

上述代码

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 分步式游戏服务器框架;

21 Jun 07:16
Compare
Choose a tag to compare

文档与日志


版本更新汇总

  • [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] 分布式事件总线

  1. [增强扩展] 将抽象类 AbstractEventBusRunner 标记为过时的,由接口 EventBusRunner 代替。
  2. [增强扩展] 分布式事件总线 EventBus 接口化,方便开发者自定义扩展。增加总线相关的 javadoc
  3. [fix] 订阅者使用自身所关联的 EventBus 处理相关事件。

关于 fix 订阅者使用自身所关联的 EventBus 处理相关事件,在此之前可能引发 bug 的场景如下

  1. 【游戏逻辑服 A】 发布事件。
  2. 【游戏逻辑服 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>

ioGame 21.9,java 高性能游戏服务器框架;netty 高性能游戏服务器框架

03 Jun 01:40
Compare
Choose a tag to compare

21.9

文档与日志


版本更新汇总

  • [core] #294 增加范围内的广播接口 RangeBroadcaster,业务参数支持基础类型(协议碎片)的简化使用
  • [core-对接文档] #293 广播文档构建器支持对参数的单独描述
  • [light-game-room] #297 模拟系统创建房间,RoomCreateContext 的使用
  • [light-game-room] #298 模拟系统创建房间,GameFlowContext 的使用
  • [core] #301 FlowContext 更新元信息后,需要立即生效(跨服调用时)
  • [内置 kit] 开放 TaskListener 接口
  • 为 SimpleRoom aggregationContext 属性提供默认值,移除 RoomCreateContext 接口的 getAggregationContext 方法,以免产生误导。

[light-game-room]

为 SimpleRoom aggregationContext 属性提供默认值


#297,模拟系统创建房间,RoomCreateContext 的使用

移除 RoomCreateContext 接口的 getAggregationContext 方法,以免产生误导。

RoomCreateContext 增加默认重载

RoomCreateContext.of(); // 无房间创建者,通常表示系统创建
RoomCreateContext.of(userId); // 房间创建者为 userId

#298 模拟系统创建房间,GameFlowContext 的使用

public void test() {
    Room room = ...;
    GameFlowContext context = GameFlowContext.of(room);
    ... 省略部分代码
}

[core]

#294 增加范围内的广播接口 RangeBroadcaster,业务参数支持基础类型(协议碎片)的简化使用

public void testRangeBroadcaster(FlowContext flowContext) {
    // ------------ object ------------
    // 广播 object
    DemoBroadcastMessage message = new DemoBroadcastMessage();
    message.msg = "helloBroadcast --- 1";
    RangeBroadcaster.of(flowContext)
            .setResponseMessage(cmdInfo, message);
    // 广播 object list
    List<DemoBroadcastMessage> messageList = List.of(message);
    RangeBroadcaster.of(flowContext)
            .setResponseMessageList(cmdInfo, messageList);

    // ------------ int ------------
    // 广播 int
    int intValue = 1;
    RangeBroadcaster.of(flowContext)
            .setResponseMessage(cmdInfo, intValue);
    // 广播 int list
    List<Integer> intValueList = List.of(1, 2);
    RangeBroadcaster.of(flowContext)
            .setResponseMessageIntList(cmdInfo, intValueList);

    // ------------ long ------------
    // 广播 long
    long longValue = 1L;
    RangeBroadcaster.of(flowContext)
            .setResponseMessage(cmdInfo, longValue);
    // 广播 long list
    List<Long> longValueList = List.of(1L, 2L);
    RangeBroadcaster.of(flowContext)
            .setResponseMessageLongList(cmdInfo, longValueList);

    // ------------ String ------------
    // 广播 String
    String stringValue = "1";
    RangeBroadcaster.of(flowContext)
            .setResponseMessage(cmdInfo, stringValue);
    // 广播 String list
    List<String> stringValueList = List.of("1L", "2L");
    RangeBroadcaster.of(flowContext)
            .setResponseMessageStringList(cmdInfo, stringValueList);
            
    // ------------ boolean ------------
    // 广播 boolean
    boolean boolValue = true;
    RangeBroadcaster.of(flowContext)
            .setResponseMessage(cmdInfo, boolValue);
    // 广播 boolean list
    List<Boolean> boolValueList = List.of(true, false);
    RangeBroadcaster.of(flowContext)
            .setResponseMessageBoolList(cmdInfo, boolValueList);
}

#301 FlowContext 更新元信息后,需要立即生效(跨服调用时)

在此之前,更新元信息后,并不会将元信息同步到 FlowContext 中,只会将元信息同步到游戏对外服中;所以在更新元信息后,紧接着执行跨服调用是不能获取新的元信息内容的。

当前 issues 会对这部分做增强,也就是在更新元信息后,会将元信息同步到 FlowContext 中;这样,在后续的跨服调用中也能获取到最新的元信息。

void test1(FlowContext flowContext) {
    // 获取元信息
    MyAttachment attachment = flowContext.getAttachment(MyAttachment.class);
    attachment.nickname = "渔民小镇";

    // [同步]更新 - 将元信息同步到玩家所在的游戏对外服中
    flowContext.updateAttachment(attachment);

    // 跨服请求
    CmdInfo helloCmdInfo = CmdInfo.of(1, 1);
    flowContext.invokeModuleMessage(helloCmdInfo);
}

@ActionController(1)
public class DemoFightAction {
    @ActionMethod(1)
    void hello(FlowContext flowContext) {
        // 可以得到最新的元信息
        MyAttachment attachment = flowContext.getAttachment(MyAttachment.class);
        log.info("{}", attachment.nickname);
    }
}

#293 广播文档构建器支持对参数的单独描述

  private void extractedDco(BarSkeletonBuilder builder) {
      // UserCmd
      builder.addBroadcastDoc(BroadcastDoc.newBuilder(UserCmd.of(UserCmd.enterSquare))
              .setDataClass(SquarePlayer.class)
              .setDescription("新玩家加入房间,给房间内的其他玩家广播")
      ).addBroadcastDoc(BroadcastDoc.newBuilder(UserCmd.of(UserCmd.offline))
              .setDataClass(LongValue.class, "userId")
              .setDescription("有玩家下线了")
      );
}

下面是生成后的对接文档预览

==================== 游戏文档格式说明 ====================
https://www.yuque.com/iohao/game/irth38#cJLdC

==================== FightHallAction 大厅(类似地图) ====================
 
路由: 1 - 2  --- 【进入大厅】 --- 【FightHallAction:94】【enterSquare】
    方法参数: EnterSquare enterSquare 进入大厅
    方法返回值: ByteValueList<SquarePlayer> 所有玩家
    广播推送: SquarePlayer ,(新玩家加入房间,给房间内的其他玩家广播)
 

路由: 1 - 5  --- 【玩家下线】 --- 【FightHallAction:154】【offline】
    方法返回值: void 
    广播推送: LongValue userId,(有玩家下线了)

[内置 kit]

开放 TaskListener 接口,TaskListener 是 TaskKit 相关的任务监听接口。

TaskListener 任务监听回调,使用场景有:一次性延时任务、任务调度、轻量可控的延时任务、轻量的定时入库辅助功能 ...等其他扩展场景。这些使用场景都有一个共同特点,即监听回调。接口提供了 4 个方法,如下

  1. CommonTaskListener.onUpdate(),监听回调
  2. CommonTaskListener.triggerUpdate(),是否触发 CommonTaskListener.onUpdate() 监听回调方法
  3. CommonTaskListener.onException(Throwable) ,异常回调。在执行 CommonTaskListener.triggerUpdate() 和 CommonTaskListener.onUpdate() 方法时,如果触发了异常,异常将被该方法捕获。
  4. CommonTaskListener.getExecutor(),指定执行器来执行上述方法,目的是不占用业务线程。

更多介绍与使用,请阅读 TaskKit (yuque.com)