Skip to content

Releases: iohao/ioGame

java netty 集群游戏服务器框架 ioGame 17.1.28

01 Jan 14:45
Compare
Choose a tag to compare

增加版本标识
增加版本标识,并在 DebugInOut 插件中显示的打印。

┏━━━━━ Debug. [(HelloAction.java:88).world] ━━━ [cmd:1 - subCmd:7 - cmdMerge:65543] ━━━ [逻辑服 [hello 游戏逻辑服] - id:[fc3348f8-4881-49e4-b94d-8cd99ab543cf]]
┣ userId: 0
┣ 参数: helloReq : HelloReq(name=112)
┣ 响应: HelloReq(name=死亡阴影3)
┣ 时间: 0 ms (业务方法总耗时)
┗━━━━━ Debug  [HelloAction.java - ioGame:17.1.28] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

业务框架处理器
增加 ActionCommandTryHandler 并作为默认的业务框架处理器。
业务框架默认是在 bolt 线程运行,如果有异常会被 bolt 捕获到日志文件中。由于控制台没有显示的打印异常信息,开发者如果对 bolt 不熟悉,是不知道有该日志文件的。当出现异常时,将会浪费开发人员的时间来排查问题,为了避免这种情况,业务框架先做捕获,并打印到控制台中,在向上抛 ex。

bolt 日志文件相关 https://www.yuque.com/iohao/game/derl0laiu2v0k104#likQv

final class ActionCommandTryHandler extends ActionCommandHandler {
    @Override
    public boolean handler(final FlowContext flowContext) {
        /*
         * 业务框架默认是在 bolt 线程运行,如果有异常会被 bolt 捕获到日志文件中,
         * https://www.yuque.com/iohao/game/derl0laiu2v0k104#likQv
         *
         * 由于没有打印到控制台,开发者如果对 bolt 不熟悉,是不会看日志文件,或者说不知道有该日志文件。
         * 为了避免这种情况,业务框架先做捕获并打印,在向上抛 ex
         *
         */

        try {
            return super.handler(flowContext);
        } catch (Throwable e) {
            log.error(e.getMessage(), e);
            throw e;
        }
    }
}

java netty 分布式游戏服务器框架 ioGame 17.1.27

14 Dec 03:35
Compare
Choose a tag to compare

#27
业务框架与网络通信框架解耦
新增 ChannelContext 通信通道接口,用于对 bolt AsyncContext、netty Channel 的包装,这样可以使得业务框架与网络通信框架解耦,为将来 ioGame 实现绳量级架构的使用做准备。

移除 FlowAttr.asyncContext 动态属性,由 FlowAttr.channelContext 代替。
业务框架模块移除网络相关的依赖 bolt、netty 等。

#28
游戏对外服 netty 编排业务钩子接口
新增 ChannelPipelineHook netty 业务编排的处理器钩子接口,用于游戏对外服。

ExternalServerBuilder 新增 channelPipelineHook 属性 ,用于自定义 netty 业务编排的处理器设置。
废弃标记 ExternalServerBuilder.channelHandlerProcessors 属性及其相关地方为过期,由 ChannelPipelineHook 来代替,使用示例如下。

public class ExternalServerBuilderApplication {
    public static void main(String[] args) {
        // netty ChannelHandler 编排
        var myChannelPipelineHook = new ChannelPipelineHook() {
            @Override
            public void initChannelPipeline(ChannelPipeline pipeline) {
                pipeline.addLast("ExternalBizHandler", new ExternalBizHandler());

                // pipeline.addFirst("ssl", ssl)
            }
        };

        // 游戏对外服构建器
        ExternalServerBuilder builder = ExternalServer.newBuilder(10100);
        builder.channelPipelineHook(myChannelPipelineHook);
    }
}

通常情况下,这样的编排方式也会更加清晰,因为代码统一在这里做编排了。开发者在自定义业务编排时,可以通过这个钩子接口,比如添加一个 SSL。

注意事项:在调用 hook 前,会经过 ExternalChannelInitializerCallback.initChannelPipeline(SocketChannel) ,
ExternalChannelInitializerCallback 接口的实现类有

  1. ExternalChannelInitializerCallbackWebsocket
  2. ExternalChannelInitializerCallbackTcp
    这些实现类中,会给 ChannelPipeline 添加上一些默认的处理器,通常是编解码相关的。

#30 简化元附加信息的使用 使用文档

在处理 action 时,我们可以通过 FlowContext.userId 可以很方便得到当前用户(玩家)id。

如果开发者想在处理 action 时,携带上一些自定义的信息时,可以通过元附加信息特性来完成。比如保存当前玩家的英雄角色 id,或者玩家的昵称,又或者是你的项目的 userId 是 string 或其他类型则可以通过元信息这一特性来兼容。

简单的说,就是你想在 FlowContext 中获取一些用户(玩家)特有的信息数据时,可以通过这个特性来实现。

// 自定义一个元信息类,实现 Attachment 元附加信息接口
@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
public class MyAttachment implements Attachment {
    @Getter
    long userId;
    String nickname;
}

@ActionController(1)
public class DemoAction {
	@ActionMethod(1)
    public void attachment(FlowContext flowContext) {
    	// 创建自定义的元附加信息对象
        MyAttachment myAttachment = new MyAttachment();
        myAttachment.userId = flowContext.getUserId();
        myAttachment.nickname = "英雄无敌3";
    	
        // 设置元信息 ----- 关键代码
        ExternalCommunicationKit.setAttachment(myAttachment);
    }

    @ActionMethod(2)
    public MyAttachment printAttachment(FlowContext flowContext) {
    	// 得到元信息,这个是在上面的方法中设置的元信息对象
        var attachment = flowContext.getAttachment(MyAttachment.class);

        return attachment;
    }
}

通过这个示例可以看出,元信息的设置与获取是简单的。
甚至你还可以配合自定义 FolwContext 特性 ,对这个扩展做更符合项目的定制,如下

// 自定义一个元信息类,实现 Attachment 元附加信息接口
@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
public class MyAttachment implements Attachment {
    @Getter
    long userId;
    String nickname;
}

public class MyFlowContext extends FlowContext {
    public String getNickname() {
        var attachment = this.getAttachment(MyAttachment.class);
        return attachment.nickname;
    }
}

@ActionController(1)
public class DemoAction {
	@ActionMethod(1)
    public void attachment(MyFlowContext flowContext) {
    	// 创建自定义的元附加信息对象
        MyAttachment myAttachment = new MyAttachment();
        myAttachment.userId = flowContext.getUserId();
        myAttachment.nickname = "英雄无敌3";
    	
        // 设置元信息 ----- 关键代码
        ExternalCommunicationKit.setAttachment(myAttachment);
    }

    @ActionMethod(3)
    public void printAttachment(MyFlowContext flowContext) {
        var nickname = flowContext.getNickname();
    	System.out.println(nickname);
    }
}

其他优化
命令解析器与源码文档逻辑分离。
优化命令对象,减少 action 类的实例化对象

java websocket 游戏服务器框架 ioGame 17.1.25 多协议支持 protobuf、json

03 Dec 06:36
Compare
Choose a tag to compare

v17.1.25 news

ActionCommandInfoBuilder 改名为 ActionCommandParser 命令解析器
将业务框架中的部分类设置为 final 权限
废弃动态属性 FlowAttr.data ,由 FlowAttr.actionBizParam 代替

#I63L7V BarSkeletonBuilderParamConfig 类的方法名变更
addActionController 标记为废弃,请使用 scanActionPackage。
addActionSend 标记为废弃,请使用 scanActionSendPackage。

因为 addActionController 、addActionSend 的方法名,会给部分开发者带来混淆。这导致部分开发者在使用时 addActionController 方法时,会多次添加 action 类。实际上只需要随意配置一个 action 类就可以了,即使有一万个action。

#I63L89 标准 action 规则

  1. 业务方法上添加注解 ActionMethod
  2. 业务方法的访问权限必须是:public
  3. 业务方法不能是:static
  4. 业务方法需要是在 action 类中声明的方法
    简单的说,标准的 action 是非静态的,且访问权限为 public 的方法。
    术语说明:在 action 类中提供的业务方法通常称为 action

#I6307A 支持多种协议:protobuf、json,并支持可扩展
现在 ioGame 支持同样的一套业务代码,无需开发者做代码的变更,就能支持多种协议的切换,如:protobuf、json。协议的切换是简单的,只需要一行代码。

简单点说,如果开发者的项目之前使用的是 json 数据来传输的,以后想改用 protobuf 来传输,是不需要改变业务方法的。框架除了内置支持的 protobuf、json 协议外,开发者还可以对协议进行扩展。

让我们先看一个 action 的业务代码片段。

@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
public class HelloReq {
    String name;
}

@ActionController(19)
public class JsonAction {
    @ActionMethod(1)
	public HelloReq hello(HelloReq helloReq) {
        helloReq.name = helloReq.name + ",hello json";
        return helloReq;
    }
}

似乎与之前介绍的并没有什么区别,至少在编写代码方式上没什么区别。在不变更代码的情况下,就能支持 json 数据协议了。

在 ioGame 中切换协议是简单的,只需要一行代码。ioGame 默认的 json 编解码器使用的是 fastjson2 来解析 json 数据,如果开发者想使用其他 json 库来做数据解析,可以通过扩展的方式,并且扩展是简单的、容易的。

public class JsonApplication {
    public static void main(String[] args) {
        // 设置 json 编解码。如果不做设置,默认使用 jprotobuf
        IoGameGlobalSetting.me().setDataCodec(new JsonDataCodec());

        // 游戏对外服端口
        int port = 10100;

        // 逻辑服
        var demoLogicServer = new JsonLogicServer();

        // 启动 对外服、网关服、逻辑服; 并生成游戏业务文档
        SimpleHelper.run(port, List.of(demoLogicServer));
    }
}