Skip to content

ErlGameWorld/agw

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AGW - Erlang 游戏服务器框架

一个基于 Erlang/OTP 的高性能、开箱即用的游戏服务器框架。以斗地主为示例,展示了完整的游戏服务器架构。


为什么选择Erlang语言开发游戏服务器

Erlang 作为构建游戏服务器(尤其是大型多人在线游戏 MMO)的后端技术,拥有几个非常突出的优势,这些优势恰好解决了游戏服务器的核心痛点。

1. 无与伦比的并发能力

  • 轻量级进程:Erlang 的进程非常轻量(内存占用小,创建销毁快),一个服务器可以轻松管理数百万个并发进程。这完美契合游戏服务器中"每个玩家连接对应一个处理逻辑"的模型。
  • 无锁并发:进程间通过消息传递通信,避免了复杂的锁竞争。这意味着在高并发下,服务器性能不会因锁争用而急剧下降,能更平稳地处理玩家峰值。

2. 天生的容错性与稳定性

  • "任其崩溃"哲学:Erlang 的核心设计是"让错误局部化"。单个玩家进程崩溃(比如因非法数据)不会影响整个服务器。监督树机制能自动重启失败的进程,确保服务持续可用。而且服务器极少会宕机。
  • 热代码升级:可以在不重启服务器的情况下动态更新游戏逻辑代码。这对需要 7x24 小时运行的在线游戏至关重要,可以实现无缝更新、修复 Bug 或添加新活动,避免停机损失。

3. 软实时性能

Erlang 被设计用于电信系统,对延迟有严格要求。其调度器和垃圾回收机制针对低延迟场景进行了优化,能保证在高负载下依然有可预测的响应时间。这对于需要快速响应的实时战斗、交互类游戏非常重要。

4. 分布式与可扩展性

Erlang 语言和 OTP 框架原生支持分布式计算。你可以轻松地将游戏世界的不同区域或功能(如聊天、战斗、经济系统)部署到多台服务器上,它们能像在同一台机器上一样透明地通信。天然支持水平扩展,可以通过增加节点来应对玩家数量的增长。

5. 强大的网络 I/O 处理

Erlang 的异步非阻塞 I/O 模型能高效处理海量 TCP 连接(如玩家连接)。对于需要长连接的实时游戏来说,这是基础保障。

6. 成熟且强大的 OTP 框架

OTP 提供了经过工业验证的构建块,如 gen_server(用于状态管理)、gen_statem(用于状态机,非常适合游戏逻辑如技能状态)、supervisor(监督进程树)等。这大大减少了从零开始构建复杂、可靠系统的难度。

7. 适合游戏逻辑的特性

  • 状态管理:Erlang 进程天然就是状态机,非常适合管理玩家状态、游戏房间状态等。
  • 消息传递:游戏中的各种事件(玩家移动、攻击、聊天)可以封装成消息,在不同进程间传递,架构清晰,易于调试和扩展。

总结

Erlang 是构建高并发、高可用、分布式的游戏服务器(特别是后端逻辑、网关、匹配系统等)的顶级选择之一。它用"轻量级进程 + 消息传递 + 容错"的哲学,优雅地解决了游戏服务器面临的并发、稳定性和扩展性难题。如果你正在开发一款需要处理海量实时玩家交互的在线游戏,尤其是对服务器稳定性和扩展性要求极高的项目,Erlang 绝对是一个值得深入评估的技术选项。


语言优势对比

1. 天然高并发(不是"优化出来的",是语言自带)

Erlang 的核心是轻量级进程(Actor 模型):

对比项 C++ / Java Erlang
并发单位 线程(贵,要池化) 进程(便宜,随便开)
单节点支撑 数千线程 几十万 ~ 上百万进程
资源映射 玩家 → 线程池中的一个任务 玩家 → 一个独立进程
状态隔离 共享内存,需加锁 完全隔离,无共享内存

为什么 Actor 模型适合游戏?

传统方案的问题:
┌─────────────────────────────────────────────────────┐
│  共享内存 + 锁                                       │
│  ┌─────┐   lock    ┌─────────┐                      │
│  │线程A│ ────────> │ 玩家数据 │ <─────── 线程B      │
│  └─────┘   unlock  └─────────┘   unlock             │
│                                                     │
│  问题:                                              │
│  1. 死锁风险 - 多个锁的获取顺序不一致                │
│  2. 竞态条件 - 锁粒度难以把握                        │
│  3. 性能瓶颈 - 锁竞争导致串行化                       │
│  4. 调试困难 - 并发 bug 难以复现                     │
└─────────────────────────────────────────────────────┘

Erlang Actor 方案:
┌─────────────────────────────────────────────────────┐
│  独立进程 + 消息传递                                 │
│  ┌─────────┐                    ┌─────────┐         │
│  │ PlayerA │  ─── 消息 ───────> │ PlayerB │         │
│  │ (进程1) │                    │ (进程2) │         │
│  └────┬────┘                    └────┬────┘         │
│       │                              │              │
│       ▼                              ▼              │
│  ┌─────────┐                    ┌─────────┐         │
│  │ 状态A   │                    │ 状态B   │         │
│  │ (独立)  │                    │ (独立)  │         │
│  └─────────┘                    └─────────┘         │
│                                                     │
│  优势:                                              │
│  1. 无锁 - 每个玩家状态独立,无竞争                  │
│  2. 隔离 - 单个玩家崩溃不影响其他玩家                │
│  3. 简单 - 消息传递模型直观易懂                      │
│  4. 可扩展 - 进程可分布到多台机器                    │
└─────────────────────────────────────────────────────┘

游戏中的自然映射:

玩家登录 → 创建一个 player 进程
进入房间 → 创建一个 game_room 进程
建立连接 → 创建一个 gateway 进程
聊天频道 → 创建一个 channel 进程

每个实体 = 一个进程,状态天然隔离,无需操心并发问题!

2. 软实时能力(很适合游戏 Tick)

BEAM 虚拟机的抢占式调度:

特性 说明 游戏场景
抢占式调度 类似 OS,每个进程执行一小段就切走 不会被某个大任务卡死
公平调度 所有进程平等获得 CPU 时间 延迟稳定可预测
优先级支持 可设置进程优先级 关键逻辑优先执行

非常适合:

┌─────────────────────────────────────────────────────┐
│  战斗 Tick     → 每帧计算,延迟稳定                  │
│  技能计算      → 复杂公式,不会卡住其他玩家          │
│  定时器        → buff / cd 精确触发                  │
│  AI 决策       → 复杂寻路,不影响主线程              │
└─────────────────────────────────────────────────────┘

性能数据:

指标 Erlang 表现 说明
进程创建 100万/秒 轻量级进程,创建开销极小
进程内存 ~2KB/进程 单机可支撑数十万玩家
消息延迟 微秒级 进程间通信无需序列化
GC 停顿 进程级 单进程 GC,无全局停顿

GC 对比:

C++/Java GC (Stop-The-World):
┌─────────────────────────────────────────────────────┐
│  时间线 ─────────────────────────────────────────>  │
│  ┌──┐ ┌──┐ ┌──┐        ┌─────────────────┐ ┌──┐    │
│  │工│ │工│ │工│        │   Stop-The-World │ │工│    │
│  │作│ │作│ │作│        │      GC 暂停     │ │作│    │
│  └──┘ └──┘ └──┘        └─────────────────┘ └──┘    │
│                              ↑                      │
│                        游戏卡顿!                    │
└─────────────────────────────────────────────────────┘

Erlang GC (进程级):
┌─────────────────────────────────────────────────────┐
│  时间线 ─────────────────────────────────────────>  │
│  ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐    │
│  │P1│ │P2│ │P3│ │P1│ │P4│ │P2│ │P5│ │P3│ │P1│    │
│  │GC│ │  │ │  │ │GC│ │  │ │GC│ │  │ │GC│ │GC│    │
│  └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘    │
│        ↑                                            │
│  各进程独立 GC,互不影响,游戏流畅                   │
└─────────────────────────────────────────────────────┘

3. 天然容错(这是大杀器)

Erlang 的哲学:Let it crash(让它崩) 而且erlang游戏服极少会宕机

传统思维:
┌─────────────────────────────────────────────────────┐
│  try {                                              │
│      // 各种异常处理                                 │
│      // 生怕程序崩溃                                 │
│  } catch (Exception e) {                            │
│      // 记录日志,尝试恢复                           │
│  }                                                  │
│                                                     │
│  问题:异常处理代码比业务代码还多!                   │
└─────────────────────────────────────────────────────┘

Erlang 思维:
┌─────────────────────────────────────────────────────┐
│  %% 正常写业务逻辑,不用 try-catch                   │
│  %% 崩了就崩了,Supervisor 会自动重启                │
│                                                     │
│  handle_info({attack, Target}, State) ->            │
│      %% 如果 Target 不存在,会崩溃                   │
│      %% 但没关系,Supervisor 会重启这个玩家进程      │
│      %% 其他玩家完全不受影响!                       │
│      NewState = do_attack(Target, State),           │
│      {noreply, NewState}.                           │
└─────────────────────────────────────────────────────┘

Supervisor 监控树架构:

                    ┌──────────────┐
                    │   agw_sup    │  ← 顶层监控
                    │  (supervisor)│
                    └──────┬───────┘
           ┌───────────────┼───────────────┐
           ▼               ▼               ▼
    ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
    │ gatewaySup   │ │ system_sup   │ │  其他服务    │
    │ (supervisor) │ │ (supervisor) │ │ (supervisor) │
    └──────┬───────┘ └──────┬───────┘ └──────────────┘
           │               │
    ┌──────┴──────┐ ┌──────┴──────┐
    ▼             ▼ ▼             ▼
┌───────┐   ┌───────┐ ┌───────┐ ┌───────┐
│gateway│   │gateway│ │player │ │game   │
│ Tcp1  │   │ Ws1   │ │ proc  │ │server │
└───────┘   └───────┘ └───────┘ └───────┘
    │             │
    ▼             ▼
 崩溃!         正常运行
    │
    └──> Supervisor 自动重启
         其他玩家完全不受影响!

游戏里的好处:

场景 传统方案 Erlang 方案
单个玩家异常 可能拖垮全服 只影响自己,自动恢复
模块有 bug 整个服务重启 局部恢复,热修复
热更新时出错 服务挂掉 回滚到旧版本继续运行

容错策略配置:

%% supervisor 配置
SupFlags = #{
    strategy => one_for_one,  %% 一个进程崩溃,只重启它自己
    intensity => 10,          %% 60秒内最多重启10次
    period => 60              %% 超过则整个 supervisor 崩溃
},

4. 热更新(很多语言做不到的核心能力)

MMO 神器:不停服更新版本

传统方案:
┌─────────────────────────────────────────────────────┐
│  1. 编译新版本                                       │
│  2. 停止服务器 ──> 玩家掉线                          │
│  3. 部署新版本                                       │
│  4. 启动服务器 ──> 玩家重连                          │
│  5. 等待玩家恢复                                     │
│                                                     │
│  停机时间: 数分钟 ~ 数十分钟                         │
│  玩家体验: 差,每次更新都掉线                        │
└─────────────────────────────────────────────────────┘

Erlang 热更新:
┌─────────────────────────────────────────────────────┐
│  1. 编译新模块                                       │
│  2. l(player).  %% 热加载                           │
│  3. 完成!                                           │
│                                                     │
│  玩家无感知,游戏继续运行                            │
│  停机时间: 0                                         │
│  玩家体验: 丝滑,完全无感                            │
└─────────────────────────────────────────────────────┘

热更新的核心能力:

能力 说明
不中断服务 代码更新期间服务持续运行
状态不丢失 玩家在线状态、游戏进度完整保留
新旧共存 新旧代码可以共存一段时间,平滑过渡
修 bug 不踢人 紧急修复无需踢掉在线玩家

实际代码:

%% 开发模式下,eSync 自动监听文件变化
%% 修改 player.erl 并保存后,自动:
1> c(player).
{ok, player}

%% 生产环境手动热更新
1> l(player).
{module, player}

%% 所有正在运行的玩家进程,下次消息处理时自动使用新代码

5. 分布式原生支持

Erlang 节点之间天然互联:

单节点 → 多节点扩展:

┌─────────────────┐     ┌─────────────────┐
│   Node A        │     │   Node B        │
│  (网关节点)     │     │  (战斗节点)     │
│                 │     │                 │
│  ┌─────────┐    │     │    ┌─────────┐  │
│  │gateway  │    │     │    │game_room│  │
│  │process  │<───┼─────┼────│ process │  │
│  └─────────┘    │     │    └─────────┘  │
│                 │     │                 │
│  天然 RPC:      │     │                 │
│  gen_server:call│─────┼───> 正常工作    │
│  完全透明!      │     │                 │
└─────────────────┘     └─────────────────┘
        │                       │
        └───────────┬───────────┘
                    ▼
            ┌──────────────┐
            │   Node C     │
            │  (中心节点)  │
            │              │
            │ 全局注册表    │
            │ 全局锁       │
            │ 跨服匹配     │
            └──────────────┘

游戏架构天然拆分:

节点类型 职责 特点
网关节点 处理连接、协议解析 可水平扩展
战斗节点 游戏逻辑计算 CPU 密集
场景节点 地图、AOI 状态密集
中心节点 全局服务、匹配 协调中心

分布式代码示例:

%% 单节点调用
gen_server:call({player, PlayerId}, get_info).

%% 跨节点调用 - 只需指定节点名
gen_server:call({player, PlayerId}, 'game_node_1@192.168.1.10', get_info).

%% 或者使用全局注册
gen_server:call({global, {player, PlayerId}}, get_info).

%% 节点连接
net_kernel:connect('game_node_2@192.168.1.11').

6. 长连接处理天花板级别

TCP 连接 ≈ 一个进程,写起来极其直观:

传统方案 (C++/Java):
┌─────────────────────────────────────────────────────┐
│  epoll / IOCP / reactor 模式                        │
│                                                     │
│  1. 创建 socket                                      │
│  2. 注册到 epoll/IOCP                               │
│  3. 事件循环中处理读写                               │
│  4. 状态机管理连接状态                               │
│  5. 处理半包、粘包                                   │
│  6. 线程池处理业务逻辑                               │
│  ...                                                │
│                                                     │
│  代码复杂,容易出错                                  │
└─────────────────────────────────────────────────────┘

Erlang 方案:
┌─────────────────────────────────────────────────────┐
│  {ok, Socket} = gen_tcp:accept(ListenSocket),       │
│  spawn(fun() -> handle_client(Socket) end),         │
│                                                     │
│  handle_client(Socket) ->                           │
│      receive                                        │
│          {tcp, Socket, Data} ->                     │
│              %% 直接处理,不用管 epoll/IOCP          │
│              handle_data(Data),                     │
│              handle_client(Socket);                 │
│          {tcp_closed, Socket} ->                    │
│              %% 连接关闭,进程自动结束               │
│              ok                                     │
│      end.                                           │
│                                                     │
│  简单直观,一个连接一个进程                          │
└─────────────────────────────────────────────────────┘

特别适合:

场景 说明
MMO 大量长连接,每个玩家独立进程
聊天系统 实时消息推送,WebSocket 天然支持
实时对战 低延迟要求,进程间通信微秒级
推送服务 百万连接,单机支撑

7. 开发效率高 心智负担少 语法简单易学

方面 传统方案 Erlang 方案
代码量 大量样板代码 OTP 行为模式封装
调试 printf / gdb 内置调试器、追踪器
测试 单元测试框架 EUnit、Common Test
文档 需要额外维护 Edoc 从代码生成
重构 IDE 支持 编译器检查

8. 成功案例

项目 类型 说明
WhatsApp 即时通讯 2百万连接/服务器,被 Facebook 190亿收购
RabbitMQ 消息队列 最流行的开源消息中间件之一
Discord 游戏语音 500万并发用户,后来部分迁移到 Rust
League of Legends 游戏 聊天服务器使用 Erlang
Call of Duty 游戏 匹配服务器使用 Erlang
魔兽世界 游戏 早期聊天和部分后台系统
皇室战争 游戏 后端服务器大量使用 Erlang

9. 适合游戏逻辑的特性

状态管理: Erlang 进程天然就是状态机,非常适合管理玩家状态、游戏房间状态等。

消息传递: 游戏中的各种事件(玩家移动、攻击、聊天)可以封装成消息,在不同进程间传递,架构清晰,易于调试和扩展。

强大的 OTP 框架: OTP 提供了经过工业验证的构建块:

OTP 组件 用途 游戏场景
gen_server 状态管理 玩家进程、房间进程
gen_statem 状态机 技能状态、战斗流程
supervisor 监督树 进程崩溃自动恢复
application 应用管理 模块化部署

10. 适用场景

场景 推荐度 说明
MMORPG ⭐⭐⭐⭐⭐ 大量玩家独立状态,完美匹配
卡牌/棋牌 ⭐⭐⭐⭐⭐ 本框架示例,斗地主完整实现
MOBA/FPS ⭐⭐⭐⭐ 匹配、聊天用 Erlang,战斗用 C++
休闲游戏 ⭐⭐⭐⭐⭐ 高并发、低延迟需求
实时对战 ⭐⭐⭐⭐⭐ WebSocket 支持良好,长连接天花板
SLG 策略 ⭐⭐⭐⭐⭐ 复杂状态管理,热更新需求
IM 聊天 ⭐⭐⭐⭐⭐ 长连接 + 高并发,天然优势

11. 需要考虑的挑战

挑战 说明 应对策略
学习曲线 函数式编程和 Erlang 特有语法需要时间适应 但是本框架提供完整示例,边学边用,开箱即可用,简单上手,完善的工具依赖
生态系统 相比 C++/Java/Go,游戏特定领域库较少 与其他技术栈配合,Erlang 做核心逻辑
人才储备 精通 Erlang 的开发者相对较少 文档完善,降低上手门槛

架构设计

整体架构

┌─────────────────────────────────────────────────────────────────┐
│                           客户端层                               │
│         Web Client (React)  │  Mobile  │  Desktop              │
└─────────────────────────────┬───────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                        网关层 (Gateway)                          │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐              │
│  │ gatewayTcp  │  │ gatewayWs   │  │ gatewayHttp │              │
│  │  (TCP)      │  │ (WebSocket) │  │   (HTTP)    │              │
│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘              │
│         │                │                │                      │
│         └────────────────┼────────────────┘                      │
│                          ▼                                       │
│                   ┌─────────────┐                                │
│                   │  gatewaySup │  监控树                        │
│                   └─────────────┘                                │
└─────────────────────────────┬───────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                        玩家进程层                                │
│              ┌──────────────┼──────────────┐                    │
│              ▼              ▼              ▼                    │
│         ┌─────────┐   ┌─────────┐   ┌─────────┐                 │
│         │ Player  │   │ Player  │   │ Player  │   玩家进程层     │
│         │ Process │   │ Process │   │ Process │                 │
│         └────┬────┘   └────┬────┘   └────┬────┘                 │
│              │              │              │                     │
│              └──────────────┼──────────────┘                     │
│                             ▼                                    │
│         ┌─────────────────────────────────────────┐              │
│         │           Game Server 游戏逻辑层         │              │
│         │   room_manager │ game_server │ ai_agent │              │
│         └───────────────────┬─────────────────────┘              │
│                             │                                    │
│                             ▼                                    │
│         ┌─────────────────────────────────────────┐              │
│         │           数据持久化层                   │              │
│         │   score_system │ eArango (ArangoDB)     │              │
│         └─────────────────────────────────────────┘              │
│                                                                  │
│                         agw 框架                                 │
└─────────────────────────────────────────────────────────────────┘

核心进程模型

客户端连接流程:

  客户端                    Gateway                    Player                  GameServer
    │                          │                         │                         │
    │──── TCP/WS 连接 ────────>│                         │                         │
    │                          │                         │                         │
    │──── cs_handshake ───────>│                         │                         │
    │<─── sc_handshake ────────│                         │                         │
    │                          │                         │                         │
    │──── cs_login ───────────>│                         │                         │
    │                          │── start_link ──────────>│                         │
    │                          │                         │── join_game ───────────>│
    │<─── sc_login ────────────│                         │                         │
    │                          │                         │                         │
    │                          │<────── 监控 ────────────│                         │
    │                          │                         │<────── 监控 ────────────│
    │                          │                         │                         │
    │──── 游戏消息 ────────────>│─── eCliMsg ────────────>│─── 游戏逻辑 ───────────>│
    │<─── 游戏响应 ────────────│<── eSendCli ────────────│<── 游戏结果 ────────────│

断线重连机制

断线重连流程:

  客户端A                    GatewayA                  Player                  新客户端A
    │                          │                         │                         │
    │──── 连接断开 ───────────>│                         │                         │
    │                          │─── DOWN 信号 ──────────>│                         │
    │                          │                         │                         │
    │                          │                         │── 启动 3 分钟定时器 ────>│
    │                          │                         │                         │
    │                          │                         │<──── 新连接 ────────────│
    │                          │                         │<──── cs_login ──────────│
    │                          │                         │                         │
    │                          │                         │── 取消定时器            │
    │                          │                         │── 更新 GatewayPid ─────>│
    │                          │                         │                         │
    │                          │                         │── 恢复游戏状态 ─────────>│
    │                          │                         │                         │
    │                          │                         │<─── 重连成功 ───────────│

挤下线机制

挤下线流程:

  老客户端                   GatewayA                  Player                  新客户端
    │                          │                         │                         │
    │                          │                         │<──── cs_login ──────────│
    │                          │                         │                         │
    │                          │<── eKickByRelogin ─────│                         │
    │<─── 连接关闭 ────────────│                         │                         │
    │                          │                         │                         │
    │                          │                         │── 更新 GatewayPid ─────>│
    │                          │                         │                         │
    │                          │                         │<─── 登录成功 ───────────│

项目结构

agw/
├── config/                    # 配置文件
│   ├── devopsGame.cfg         # 游戏服务器配置
│   ├── devopsCenter.cfg       # 中心服务器配置
│   ├── devopsCross.cfg        # 跨服服务器配置
│   ├── sys.config             # OTP 系统配置
│   └── vm.args                # Erlang VM 参数
│
├── include/                   # 头文件
│   ├── common.hrl             # 通用宏定义
│   ├── game.hrl               # 游戏记录定义
│   ├── gateway.hrl            # 网关记录定义
│   ├── protoMsg.hrl           # 协议消息定义
│   └── server.hrl             # 服务器定义
│
├── proto/                     # 协议定义
│   ├── 0_common.mpdf          # 公共类型
│   ├── 1_login.mpdf           # 登录协议
│   └── 2_role.mpdf            # 角色协议
│
├── src/                       # 源代码
│   ├── gateway/               # 网关模块
│   │   ├── gateway.erl        # 网关启动入口
│   │   ├── gatewayTcp.erl     # TCP 网关
│   │   ├── gatewayWs.erl      # WebSocket 网关
│   │   ├── gatewayHttp.erl    # HTTP 网关
│   │   └── gatewaySup.erl     # 网关监控树
│   │
│   ├── player/                # 玩家模块
│   │   └── player.erl         # 玩家进程
│   │
│   ├── handler/               # 消息处理器
│   │   ├── loginHer.erl       # 登录消息处理
│   │   └── roleHer.erl        # 角色消息处理
│   │
│   ├── game/                  # 游戏逻辑
│   │   ├── game_server.erl    # 游戏房间服务
│   │   ├── room_manager.erl   # 房间管理器
│   │   ├── score_system.erl   # 积分系统
│   │   ├── card/              # 牌型判断
│   │   │   ├── cards.erl      # 发牌洗牌
│   │   │   ├── card_rules.erl # 牌型规则
│   │   │   └── card_checker.erl# 出牌检测
│   │   └── ai/                # AI 托管
│   │       ├── ai_agent.erl   # AI 代理
│   │       ├── ai_logic.erl   # AI 逻辑
│   │       └── ai_supervisor.erl
│   │
│   ├── proto/                 # 协议编解码
│   │   └── protoMsg.erl       # 协议消息处理
│   │
│   └── server/                # 服务器管理
│       └── devops.erl         # 运维配置加载相关
│
├── priv/                      # 静态资源
│   ├── static/                # 前端静态文件
│
├── cli/                       # 前端客户端
│   └── src/                   # React 游戏客户端
│
├── rebar.config               # Rebar3 配置
├── Emakefile                  # Emake 配置
└── start.bat                  # Windows 启动脚本

工具库与依赖

依赖库总览 除了ibrowse 其他库均在本github下

库名 类型 功能说明
eNet 网络 TCP/UDP 高并发网络库
eWSrv 网络 WebSocket/Http 服务器
eArango 存储 ArangoDB 数据库驱动
ePtDirty 存储 脏数据自动检测与维护
eGLock 并发 全局锁用于避免大量需要单进程顺序处理的数据在单进程处理瓶颈
gTimer 定时 全局定时器用于管理全服的定时器
ranks 游戏 排行榜系统
eAccess 安全 敏感词过滤
eGbh 行为 通用行为模式
eFaw 并行 工厂/工人模式用于处理繁重也与玩家状态不强相关的业务
eSync 开发 代码自动编译,热更新配置表自动加载
genProto 开发 协议生成工具支持生成Erlang/Lua/C#/Ts语言
genCfgs 开发 配置导表工具支持xlsx文件转换为erlang,elixir,lua,json,xml
eLog 基础 简单易用高效的日志系统
eUtils 基础 通用工具函数
jiffy 基础 JSON 编解码
其他 基础 本github还有其他一些游戏相关的工具可以多多探索

快速开始

环境要求

  • Erlang/OTP 27+
  • Rebar3/eMake (构建工具)
  • Python 3.7+ (配置导表工具) release版本不需要安装python
  • Node.js 18+ (前端/GM工具) release版本不需要安装node

安装依赖

# 编译项目
rebar3 compile 
本项目依赖库有一些nif 如果要编译的话依赖于c/c++编译环境 需要安装gcc或者c++编译器, windows平台可以安装Visual Studio的C++编译工具,然后需要添加环境变量 参见 eUtils库的'erlangVS环境编译nifdll.md' 这个文档
然后还会依赖本github下 eNpc库 需要先将eNpc库rebar3 escripte 然后将生成的执行文件 eNpc eNpc.cmd 复制到elrang安装目录下的bin目录下 以便编译eNpc依赖库的nif文件
如果闲nif编译麻烦 可以将有nif编译的库的rebar.config文件中带"eNpc compile" 这样的都注释掉

%  {pre_hooks,
%     [{"", compile, "eNpc compile"}]}.
%
% {post_hooks,
%    [{"", clean, "eNpc clean"}]}.


# 安装前端依赖
cd cli && npm install

# 启动开发服务器
cd cli && npm run dev

# 打包生产版本
cd cli && npm run build
# 然后将 dist 文件复制到 priv/static 目录下
# 访问 http://127.0.0.1:9200 会自动加载游戏页面

# GM 工具依赖
gmSrv:start(Port).

启动服务器

# Windows
start.bat

# Linux
./config/startGame.sh

访问服务

服务 地址
TCP 端口 9100
WebSocket ws://127.0.0.1:9300
HTTP API http://127.0.0.1:9200
游戏客户端 http://127.0.0.1:9200

配置说明

服务器配置 (config/devopsGame.cfg)

%% 服务器类型 [game | center | cross]
{type, game}.

%% 服务器 ID
{server_id, 1}.

%% 网络端口
{port, 9100}.        %% TCP
{ws_port, 9300}.     %% WebSocket
{web_port, 9200}.    %% HTTP

数据库配置 (config/sys.config)

{eArango, [
    {sisDb, {
        [{baseUrl, <<"http://127.0.0.1:8529">>},
         {dbName, <<"sis">>},
         {user, <<"root">>},
         {password, <<"******">>},
         {poolSize, 128}],
        [{reconnect, true},
         {backlogSize, 1024}]
    }}
]}

协议定义

协议使用自定义 .mpdf 格式,位于 proto/ 目录:

%% 登录请求
cs_login {
    string name;
}

%% 登录响应
sc_login {
    int32 result;
    string playerId;
    playerInfo player;
}

%% 出牌请求
cs_play {
    repeated card cards;
}

%% 出牌响应
sc_player_played {
    int32 playerIdx;
    repeated card cards;
}

生成协议代码:

genProto.bat  # Windows

导表

具体参见 genCfgs 工具说明文档。


许可证

MIT License


贡献

欢迎提交 Issue 和 Pull Request!


联系方式

如有问题,请提交 Issue 或联系作者。

About

一个基于 Erlang/OTP 的高性能、开箱即用的游戏服务器框架,适用于MMORPG/卡牌/棋牌/休闲游戏/SLG等各种类型游戏后端开发。

Resources

License

MIT, MIT licenses found

Licenses found

MIT
LICENSE
MIT
LICENSE.md

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors