Go to file
kercylan98 acc468492f feat: 支持向 server.Server 绑定一些数据 2024-01-23 16:53:42 +08:00
.github other: 版本管理调整 2024-01-14 19:17:22 +08:00
configuration docs: 优化 README.md 导航中无法跳转结构体的情况 2024-01-15 10:41:10 +08:00
examples/internal docs: 优化泛型约束类型文档显示 2024-01-14 19:15:25 +08:00
game docs: 优化 README.md 可读性 2024-01-15 17:27:02 +08:00
notify docs: 优化 README.md 可读性 2024-01-15 17:27:02 +08:00
planner docs: 优化 README.md 可读性 2024-01-15 17:27:02 +08:00
server feat: 支持向 server.Server 绑定一些数据 2024-01-23 16:53:42 +08:00
utils test: super.BitSet 完善测试用例 2024-01-22 14:05:11 +08:00
.codacy.yml other: 排除 codacy 检查 md 文件,(#43) (#44) (#45) (#46) (#47) (#48) (#49) (#50) (#51) (#52) 2023-12-27 16:41:59 +08:00
.gitignore 有限状态机实现 2023-05-26 10:49:16 +08:00
CHANGELOG.md chore(master): release 0.4.2 2023-12-26 11:17:03 +08:00
CODE_OF_CONDUCT.md Create CODE_OF_CONDUCT.md 2023-05-30 14:29:59 +08:00
CONTRIBUTING.md docs: README.md 及 CONTRIBUTING.md 完善 2023-08-02 18:43:12 +08:00
LICENSE LICENSE 2023-05-29 20:35:03 +08:00
README.md docs: 优化项目文档 2024-01-14 18:33:01 +08:00
go.mod other: 依赖版本更新 2024-01-16 18:20:14 +08:00
go.sum other: 依赖版本更新 2024-01-16 18:20:14 +08:00
local-doc.bat 文档及许可 2023-05-29 20:15:13 +08:00
local-doc.sh 代码扫描问题处理 (#3) (#4) 2023-05-30 14:24:03 +08:00
qodana.yaml build: 更新依赖版本 2023-08-23 19:46:02 +08:00

README.md

Minotaur

Go doc

Minotaur 是一个基于 Golang 1.20 编写的服务端开发支持库,其中采用了大量泛型设计,主要被用于游戏服务器开发,但由于拥有大量通用的功能,也常被用于 WEB 开发。

特色内容

mindmap
  root((Minotaur))
    所有功能均为可选的,引入即用
    基于动态分流的异步消息支持
    兼容各类实现的帧同步组件
    多级消息路由器,轻松搭建跨服服务
    开箱即用的配置导表工具
    强大的 utils 包
      常用的切片、map、随机、时间、数学、文件、类型转换等工具函数
      适用于定时、编排、组合、匹配、校验等行为的组件
      版本比较、重试、耗时计数等super package
    活动、任务、AOI、寻路、战斗、移动、房间等通用游戏组件
    针对扑克牌玩法的大量支持

Server 架构预览

server-gdi.svg

安装

注意:依赖于 Go 1.20 +

运行以下 Go 命令来安装软件包:minotaur

$ go get -u github.com/kercylan98/minotaur

用法

本地文档

可使用 godoc 搭建本地文档服务器

安装 godoc

git clone golang.org/x/tools
cd tools/cmd
go install ...

使用 godoc 启动本地文档服务器

godoc -http=:9998 -play

Windows

.\local-doc.bat

Linux or MacOS

chmod 777 ./local-doc.sh
./local-doc.sh

文档地址

简单回响服务器

创建一个基于Websocket创建的单线程回响服务器。

package main

import (
	"github.com/kercylan98/minotaur/server"
)

func main() {
	srv := server.New(server.NetworkWebsocket)
	srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) {
		conn.Write(packet)
	})
	if err := srv.Run(":9999"); err != nil {
		panic(err)
	}
}

访问 WebSocket 在线测试 进行验证。

Websocket地址: ws://127.0.0.1:9999

分流服务器

分流服务器可以将消息分流到不同的分组上,每个分组中为串行处理,不同分组之间并行处理。

关于分流服务器的思考:

  • 当游戏需要以房间的形式进行时,应该确保相同房间的玩家处于同一分流中,不同房间的玩家处于不同分流中,这样可以避免不同房间的玩家之间的消息互相阻塞;
    • 这时候网络 IO 应该根据不同的游戏类型而进行不同的处理,例如回合制可以同步执行,而实时游戏应该采用异步执行;
  • 当游戏大部分时候以单人游戏进行时,应该每个玩家处于自身唯一的分流中,此时非互动的消息造成的网络 IO 采用同步执行即可,也不会阻塞到其他玩家的消息处理;
package main

import "github.com/kercylan98/minotaur/server"

func main() {
	srv := server.New(server.NetworkWebsocket)
	srv.RegConnectionOpenedEvent(func(srv *server.Server, conn *server.Conn) {
		// 通过 user_id 进行分流,不同用户的消息将不会互相阻塞
		srv.UseShunt(conn, conn.Gata("user_id").(string))
	})
	srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) {
		var roomId = "default"
		switch string(packet) {
		case "JoinRoom":
            // 将用户所处的分流渠道切换到 roomId 渠道,此刻同一分流渠道的消息将会按队列顺序处理
            srv.UseShunt(conn, roomId)
		case "LeaveRoom":
            // 将用户所处分流切换为用户自身的分流渠道
            srv.UseShunt(conn, conn.Gata("user_id").(string))
		}
	})
	if err := srv.Run(":9999"); err != nil {
		panic(err)
	}
}

该示例中模拟了用户分流渠道在自身渠道和房间渠道切换的过程,通过UseShunt对连接分流渠道进行设置,提高并发处理能力。

服务器死锁检测

Minotaur内置了服务器消息死锁检测功能,可通过server.WithDeadlockDetect进行开启。

package main

import (
	"github.com/kercylan98/minotaur/server"
	"time"
)

func main() {
	srv := server.New(server.NetworkWebsocket,
		server.WithDeadlockDetect(time.Second*5),
	)
	srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) {
		time.Sleep(10 * time.Second)
		conn.Write(packet)
	})
	if err := srv.Run(":9999"); err != nil {
		panic(err)
	}
}

在开启死锁检测的时候需要设置一个合理的死锁怀疑时间,该时间内消息没有处理完毕则会触发死锁检测,并打印WARN级别的日志输出。

计时器

在默认的server.Server不会包含计时器功能,可通过server.WithTicker进行开启,例如:

package main

import "github.com/kercylan98/minotaur/server"

func main() {
	srv := server.New(server.NetworkWebsocket, server.WithTicker(-1, 50, 10, false))
	if err := srv.Run(":9999"); err != nil {
		panic(err)
	}
}

也可以通过timer.GetTicker获取计时器进行使用,例如:

package main

import (
	"fmt"
	"github.com/kercylan98/minotaur/utils/timer"
	"github.com/kercylan98/minotaur/utils/times"
	"sync"
)

func main() {
	var ticker = timer.GetTicker(10)
	var wait sync.WaitGroup
	wait.Add(3)
	ticker.Loop("LOOP", timer.Instantly, times.Second, timer.Forever, func() {
		fmt.Println("LOOP")
		wait.Done()
	})
	wait.Wait()
}

在分布式环境中,如果存在类似于多服务器需要同时间刷新配置时,可使用Cron表达式设置定时任务。

基于xlsx文件的配置导出工具

该导出器的xlsx文件配置使用JSON语法进行复杂类型配置,具体可参考图例

导出 JSON 文件(可供客户端直接使用,包含索引的配置导出后为键值模式,可直接读取)

Flags:
  -e, --exclude string   excluded configuration names or display names (comma separated) | 排除的配置名或显示名(英文逗号分隔)
  -h, --help             help for json
  -o, --output string    directory path of the output json file | 输出的 json 文件所在目录路径
  -p, --prefix string    export configuration file name prefix | 导出配置文件名前缀
  -t, --type string      export server configuration[s] or client configuration[c] | 导出服务端配置[s]还是客户端配置[c]
  -f, --xlsx string      xlsx file path or directory path | xlsx 文件路径或所在目录路径

expoter.exe json -t s -f xlsx_template.xlsx -o ./output

导出结果示例

{
  "1": {
    "b": {
      "Id": 1,
      "Count": "b",
      "Info": {
        "id": 1,
        "name": "小明",
        "info": {
          "lv": 1,
          "exp": {
            "mux": 10,
            "count": 100
          }
        }
      },
      "Other": [
        {
          "id": 1,
          "name": "张飞"
        },
        {
          "id": 2,
          "name": "刘备"
        }
      ]
    }
  }
}

导出 Golang 文件

Flags:
  -e, --exclude string   excluded configuration names or display names (comma separated) | 排除的配置名或显示名(英文逗号分隔)
  -h, --help             help for go
  -o, --output string    output path | 输出的 go 文件路径
  -f, --xlsx string      xlsx file path or directory path | xlsx 文件路径或所在目录路径
expoter.exe go -f xlsx_template.xlsx -o ./output

使用示例

package main

import (
	"fmt"
	"config"
)

func main() {
	fmt.Println(config.EasyConfig.Id)
}

持续更新的示例项目

贡献者列表

参与贡献请参考 CONTRIBUTING.md 贡献指南。

联系方式

JetBrains OS licenses

Minotaur had been being developed with GoLand IDE under the free JetBrains Open Source license(s) granted by JetBrains s.r.o., hence I would like to express my thanks here.