Skip to content

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

Compare
Choose a tag to compare
@iohao iohao released this 14 Dec 03:35
· 512 commits to main since this release

#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 类的实例化对象