ephenation源代码研究

2012-12-11

引子

折腾三天多,总算把一个开源的代码给跑起来了
前后给人家老外发了5个英文邮件…
安装各种库依赖,还调试代码找bug
连续熬夜二天,在windows ubuntu10.04 12.10三个系统上尝试
把显卡驱动重装了好几次,还把ubuntu 12.10的系统搞崩了
….终于结束了

主函数流程

cmd目录,server中,main函数在pheenadv.go文件中。
main函数中,先是flag分析参数
读配置文件
从配置文件中读入sql信息,用ephenationdb建立连接
处理各个flag参数,然后就进入到SetupListenForClient函数。
该函数在listener.go中实现
此函数运行一个后台goroutine做循环,调用Accept接受连接
每个新来的连接直接起一条goroutine处理
调用go ManageOneClientWLuBlWLqWLa,这个函数在manageclients.go文件中
这个函数会把conn等信息搞到一个user数组中,每个对应一个user

再回头看,SetupListenForClient是起的goroutine,马上就返回到main中,继续往下读

go chunkdb.Poll_Bl()
go ProcAutosave_Rlu()
go ProcPurgeOldChunks_Wlw()
go CatchSig()

都是几个后台的goroutine…
然后是ManageMonstersWLwWLuWLqWLmBlWLc()注释说这个永不返回

文件结构

procs.go 调度,周期性的清除地图缓存,更新怪物状态,位置,清除和生成怪物,保存用户 monster.go 处理怪物相关的
pheenadv.go main所在的文件,调用其它文件完成主流程,还有几个跟sql相关的函数
listener.go 处理客户端来的消息,编码协议调用对应函数。向客户端发数据也会经过这里
config.go 一些默认的配置数据
parse.go 压缩和解压字节数组
player.go 玩家,里面的函数只有处理client相关的才被调用到
manageclients.go user跟player不是一个东西
globalUser.go user类型的一些方法,被全局部使用
combat.go 处理战斗相关的
specialcommands.go
我研究了一下作者,前身是做mud游戏的。其实游戏内部的命令跟mud一样都是文字驱动的 某些文字就是command。这个文件就是实现这些命令。大多数的工作仅仅是客户端发条命令消息过来, 服务端就回一命消息过去,仅此而已。
worldcache.go chunk的一个缓存层,就是一个map加一个链表,注意多线程访问时的锁
activeblocks.go

协议

服务端收到连接后,先会向客户端发送协议版本
如果玩家状态是In,处理逻辑就是移动和攻击的一些指令处理
2字节的length,1字节的命令
在src/clientprot下的文件clientprot.go是对应的各种消息的编码

总体设计

服务器控制所有事情。决定player位置,怪物。客户端只负责显示。它将玩家的动作转换成协议,根据服务端发来的请求更新显示。

世界数据

世界组织成0.5米的立方体。几种主要类型的块:

  • 被动块:只是看起来像某东西,比如墙
  • 表示块:客户端画成一些不同的东西,比如树
  • trigger块:看不见。会检测用户的动作,比如开门,播放声音,奖励等

块被组织成32*32*32的chunks。当客户端想绘制世界时,向服务端请求chunk, 这些chunk被压缩然后发过来。客户端会保存局部cache的chunk。每个block一个 字节,也就是最多有256种block。对于已有的块,使用checksum这样可以只请求信息而不是请求数据。

用户控制

玩家想移动时,向服务端发"start moving"请求。服务端会定期的将位置更新发回客户端,以及它周围的玩家。频率是每秒10次。

优化

  • 移动玩家或monster很高效
  • monster的ai很受限
  • 只要周围没有玩家,就移除monster
  • 只广播可见距离的玩家消息
  • 用四叉树管理玩家和怪物

玩家属性

因为玩家属性可能会很高,所以其实是归一化到0-1之间的。比如exp(-v)

后记

不想看了。代码写得比较挫,服务器基础架构方面值得学习的东西几乎没有。
高并发请求的处理很偷懒,直接借用go的语言优势,每来一个连接都开一条goroutine
连login server, map server或者game server这些都没有逻辑分离分开。
偏应用的地图生成之类的又看不懂。地图交互时传输checksum倒可以借鉴。

源代码分析ephenation