Home
Softono

Dangkang

Open source Apache-2.0 Java
19
Stars
3
Forks
7
Issues
4
Watchers
3 years
Last Commit

 About Dangkang

当康系统(模块化可扩展游戏服务器软件系统),Java编写的游戏服务器支持系统。

Platforms

Web Self-hosted

Languages

Java

Links

Need Help Installing Dangkang?

We provide expert installation service for this software. Our team will install, configure, and secure Dangkang on your server. plans start at just $30.

项目介绍

项目名称来由

dangkang(当康),当康名字来源于《山海经》中的瑞兽,“﹝ 钦山 ﹞有兽焉,其状如豚而有牙,其名曰当康,其鸣自叫,见则天下大穰。”

项目简介

当康系统,是一个Java编写的游戏服务器框架,封装了一些常用的游戏服务器功能,为游戏服务器开发提供帮助。

已实现功能

  • 快速启动游戏服务,让开发者只用关心业务逻辑
  • 可配置功能支持
  • 代码热修复和类编织支持
  • 外置模块(jar包级别)的热插拔和更新
  • 配置中心和GM后台
  • 常用的游戏功能支持,如下
    • 简单的角度、碰撞计算
    • 敏感数据处理
    • 游戏进程内机器人功能
    • 随机名称生成器
    • 模拟游戏客户端
    • excel文件读写
    • GM功能支持
    • 基于数据库实现的全局ID自增器
    • 二维码读取和生成
    • 其他常用的工具类等

下一步计划

  • 增加项目文档
  • 增加示例项目
  • 完善和优化已有功能,修补漏洞和BUG
  • 提供UI操作界面
  • 基于表达式或脚本的业务代码解释和执行,为不熟悉服务端开发的开发者提供支持

项目链接

项目说明

项目结构

dangkang
├── dk-agent -- 代码热修复和模块热更新基础支持
├── dk-autoconfigure -- 项目配置项自动配置支持,spring-boot项目使用
├── dk-common -- 通用工具类、常量、注解
├── dk-core -- 项目核心功能和部分游戏功能接口
├── dk-domain -- 项目中通用POJO类定义
├── dk-game-core -- 通用游戏功能支持
└── dk-impl-basic -- 常用工具和可配置功能的一些基础实现,新增可配置功能的基本实现都在该模块下添加
    ├── dk-basic-da -- 关于数据访问的一些基础实现,用于功能快速测试和验证,不建议用于实际项目
    ├── dk-basic-excel -- excel读写功能的基础支持,依赖POI
    ├── dk-config-center-jdbc -- 使用数据库实现的配置中心
    ├── dk-config-client -- 配置中心客户端支持(提供对非WEB项目和非spring boot项目的支持)
    ├── dk-db-id-incrementer -- 使用数据库实现的id自增器
    ├── dk-gm -- 当康游戏基础GM功能的实现
    ├── dk-gm-console -- 当康游戏GM后台功能的实现
    ├── dk-name-generator-cn -- 简体中文名称生成器,该项目生成的名称符合中文名传统起名习惯
    ├── dk-name-generator-foreign-cn -- 简体中文形式的外国人名称生成器实现项目
    └── dk-qr-code -- 二维码生成和解析功能

模块说明

  • dk-agent
    • 使用javaagent,实现代码的热修复
    • 使用并增强ClassFileTransformer,提供热修复功能的快速扩展
    • 为组件注入提供支持
  • dk-autoconfigure
    • 支持当康系统配置参数的IDE快速配置
  • dk-common
    • 声明项目中通用的注解
    • 提供常用的工具类
    • 部分通用常量声明
  • dk-core
  • dk-domain
    • 项目中通用POJO类定义
  • dk-game-core
  • dk-impl-basic
    • 提供一些非必要功能的独立实现

使用示例

示例项目链接

快速启动

引入当康项目的maven仓库:

  • github仓库
    <repositories>
        <repository>
            <id>dangkang-repo</id>
            <url>https://raw.github.com/fagarine/mvn-repo/master/</url>
            <snapshots>
                <enabled>true</enabled>
                <updatePolicy>always</updatePolicy>
            </snapshots>
        </repository>
    </repositories>
    
  • 码云仓库
    <repositories>
        <repository>
            <id>dangkang-repo</id>
            <url>https://gitee.com/fagarine/mvn-repo/raw/master/releases/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
                <updatePolicy>always</updatePolicy>
            </snapshots>
        </repository>
    </repositories>
    

通过配置项快速启动游戏服务

引入项目依赖

<dependency>
    <groupId>cn.laoshini.dk</groupId>
    <artifactId>dk-starter</artifactId>
    <version>${dangkang.version}</version>
</dependency>

新建配置文件,文件名随便(建议使用application.properties名称,项目中加入spring-boot-autoconfigure依赖可借助IDE辅助配置),在配置文件中加入如下配置信息:

# 游戏服id
dk.game.server.id=101
# 游戏服名称
dk.game.server.name=当康大穰
# 游戏服监听端口
dk.game.server.port=9421

添加项目启动类:

public class GameServerStarter {
    public static void main(String[] args){
        // 传入配置文件路径,启动服务
        DangKangGameStarter.get().propertyConfigs("application.properties").start();
    }
}

启动GameServerStarter的main()方法,就可以启动一个监听在9421端口的TCP游戏服。

以上这种方式启动的只是一个没有任何业务的游戏服,这个项目演示了如何添加游戏功能。

更多配置信息,详见DangKangGameProperties类DangKangGameServerProperties类。 自动配置和启动支持入口类:DkGameServerAutoConfiguration类

自定义启动方式

引入项目依赖

<dependency>
    <groupId>cn.laoshini.dk</groupId>
    <artifactId>dk-core</artifactId>
    <version>${dangkang.version}</version>
</dependency>

只启动当康容器和基础功能支持

public class GameStartMain {
    public static void main(String[] args){
        // 项目包路径前缀,用于组件扫描和功能注入等
        String[] packages = new String[] {"com.company.xxx"};

        // 自己项目中没有使用Spring
        DangKangStarter.startByNonSpring(packages);
        // 或者
        DangKangGameStarter.get().packagePrefixes(packages).start();

        // 如果项目中使用了Spring,则应该使用当康系统来加载Spring配置文件
        ApplicationContext context = DangKangStarter.startBySpringXmlFile(packages, "classpath:applicationContext.xml");
        // 或者
        ApplicationContext context = DangKangGameStarter.get().packagePrefixes(packages).springConfigs("classpath:applicationContext.xml").start();
    }
}

快速启动游戏服务器线程

public class GameStartMain {
    public static void main(String[] args){
        // 项目包路径前缀,用于组件扫描和功能注入等
        String[] packages = new String[] {"com.company.xxx"};

        ApplicationContext context = DangKangGameStarter.get().packagePrefixes(packages)
            // 添加一个TCP服务器线程注册器,具体功能详见IGameServerRegister
            .gameServer(Registers.newTcpGameServerRegister().setPort(9420).setGameName("游戏名称"))
            // 添加一个游戏消息类注册器,系统将通过注册的消息超类,扫描其所有子类,自动识别消息
            .message(Registers.newDangKangCustomMessageRegister())
            // 添加一个消息处理类注册器,系统通过消息id与扫描到的Handler关联,当消息到达时,自动识别并执行对应的handler逻辑
            .messageHandler(Registers.newDangKangMessageHandlerRegister())
            // 如果项目使用了Spring,填写Spring配置文件路径
            .springConfigs("classpath:applicationContext.xml")
            .start();

        // 可以通过如下方法,获取本进程中所有已注册的游戏服务器id
        GameServers.getAllServerId();
    }
}

游戏服功能详见net包

如果要使用部分游戏特有功能,还需要引入dk-game-core依赖

<dependencies>
    <dependency>
        <groupId>cn.laoshini.dk</groupId>
        <artifactId>dk-core</artifactId>
        <version>${dangkang.version}</version>
    </dependency>
    <dependency>
        <groupId>cn.laoshini.dk</groupId>
        <artifactId>dk-game-core</artifactId>
        <version>${dangkang.version}</version>
    </dependency>
</dependencies>

其中已支持的功能:

  • 游戏客户端模拟,使用netty实现
  • 用户id、角色id自动生成的基本实现,使用时依赖id自增器功能
  • 机器人(包括行为树和有限状态机两种形式)功能的支持

关于热修复

最小依赖方式,添加dk-agent依赖,启动项中,添加javaagent参数,如:java -cp -javaagent:dk-agent-1.0.0-SNAPSHOT.jar -jar game.jar GameStartMain

<dependency>
    <groupId>cn.laoshini.dk</groupId>
    <artifactId>dk-agent</artifactId>
    <version>${dangkang.version}</version>
</dependency>

以下代码示范如何调用代码热修复功能

public class GameStartMain {
    public static void main(String[] args){
        // 如果使用最小依赖dk-agent,可通过如下方法热修复代码
        DangKangAgent.redefineClass(clazz, bytes);
        
        // 如果添加了dk-core依赖,但是未启动当康容器,可以直接使用工具类热修复代码
        HotfixUtil.redefineClass(hotfixFile);

        // 如果启动了当康系统容器,添加class文件到热修复文件目录后,通过以下方式调用热修复功能(热修复代码class文件默认存放目录为项目根目录/hotfix目录下;这个目录名可配置,配置项名称为:dk.hotfix)
        SpringContextHolder.getBean(HotfixManager.class).doHotfix("unique key");
    }
}

关于外置模块

  • 外置模块是指项目功能独立于项目启动包之外,可以在项目启动后热插拔与更新的功能模块
  • 外置模块以jar为载体,一个jar包对应一个模块
  • 外置模块的jar包默认放在项目根目录下/modules目录,该目录可通过配置项(dk.module)设置

注意:要使用外置模块功能,需要先保证当康系统容器已启动成功,外置模块功能通过ModuleManager类调用

关于可配置功能

说明

可配置功能,是为了实现功能的多样化实现,以及依赖功能的自动注入,以及功能实现快速选择。

可配置功能的使用

  • 声明配置功能接口
  • 添加@ConfigurableFunction注解,并通过注解中的key()指定一个唯一的key,这个key也是通过配置项选择功能实现对象的配置项名称
  • 给接口添加实现类
  • 给实现类添加@FunctionVariousWays注解,如果不是默认实现,需要通过value()指定实现对象的名称
  • 添加可配置功能依赖,通过全局变量方式添加,且需要给变量添加@FunctionDependent注解

注意:该功能需要在启动了当康系统容器时才能生效,具体详见function包

关于配置中心

  • 配置中心服务端是个springboot项目,可直接打包启动,依赖于数据库,已提供基本的游戏服配置信息处理接口,用户可在该基础上丰富更多功能。
  • 配置中心客户端是个普通项目,可直接添加到项目依赖中,例如:
      <dependency>
          <groupId>cn.laoshini.dk</groupId>
          <artifactId>dk-config-client</artifactId>
          <version>${dangkang.version}</version>
      </dependency>
    
    其启动时依赖了几个配置项,具体配置项见DangKangConfigCenterProperties类,默认配置文件名为bootstrap.properties或config-client.properties,也可以是yaml文件,如果用户要使用自定义的文件名,需要通过如下方式指定:
      public class GameStartMain {
          public static void main(String[] args){
              DangKangGameStarter.get()
              // 使用自定义配置文件作为配置中心客户端配置文件
              .configClientFile("xxx.properties")
              .packagePrefixes(packages).springConfigs("classpath:applicationContext.xml").start();
          }
      }
    
    如果想要使用配置信息的自动刷新功能,则需要在依赖了配置项的类上添加@RefreshScope注解,当配置信息更新后,通过配置中心服务器${contextPath}/game/server/refresh网络接口发起刷新操作。 需要注意的是,配置中心的自动刷新依赖于MQ,系统默认使用rabbitmq

关于姓名生成器

添加依赖,中文名称生成器依赖:

<dependency>
    <groupId>cn.laoshini.dk</groupId>
    <artifactId>dk-name-generator-cn</artifactId>
    <version>${dangkang.version}</version>
</dependency>

中文形式的外国人名称生成器依赖:

<dependency>
    <groupId>cn.laoshini.dk</groupId>
    <artifactId>dk-name-generator-foreign-cn</artifactId>
    <version>${dangkang.version}</version>
</dependency>

使用示例:

public class PlayerService {
    @FunctionDependent
    private Func<INameGenerator> nameGenerator;

    private List<String> batchName() {
        // 批量生成姓名,一次返回6个
        return nameGenerator.get().batchName(6);
    }
    
    private String newName() {
        // 随机生成并返回一个名称
        return nameGenerator.get().newName();
    }
}

更多细节可以查看INameGenerator类和其实现类

工具类

  • 日志工具类,当调用其中的方法记录日志时,会自动记录下调用类和方法名以及行号等信息,使用方式如下:
        LogUtil.debug("就是想打个日志");
        LogUtil.info("游戏服[{}]开始启动", "我的游戏");
        LogUtil.error("这是个异常", e);
        LogUtil.c2sMessage("客户端到达消息:{}", message);
    
    要保证日志能正确输出,需在日志配置文件中添加一个名为"cn.laoshini.dk"的logger; 需要注意的是,游戏交互消息日志独立配置,需要单独添加一个名为"DK_MESSAGE"的logger。 具体详见LogUtil
  • Class工具类,提供了一系列批量查找类的方法,具体详见ClassUtil
  • 反射工具类,提供了一些常用的反射工具,具体详见ReflectUtilReflectHelper
  • JSON文件读写工具类,提供了简单的JSON文件读写功能,具体详见JsonUtil
  • Excel文件读写工具类,提供了简单的Excel文件读写功能,具体详见ExcelUtil
  • 二维码生成和解析工具类,提供了简单的二维码图片读写功能,具体详见QrCodeUtil

更多的工具类详见dk-common的util包dk-core的util包

特别说明

由于该项目前后断断续续数次重构,但是项目中留有部分已不用的类未清除,且重构后未能得到验证,所以可能有些地方显得多余或不合理,后期会找时间清理一遍。

其他

欢迎star/fork,欢迎学习/使用/交流,期待你的加入和贡献代码!