Hey,大家好!我是 Bill “LtRandolph” Clark,一名英雄联盟的游戏工程师。许多 Rioter 工程师关注大量的内容需要直接发送给玩家问题——这是两个我最近最喜欢的例子之一,包括最新的冠军Jhin及项目重构的支持。而我的团队使得这个过程变得又快有简单。

我们有一个简单的目标:即允许参加游戏试玩项目的暴民,能够创建两倍于任何给定的LoL(英雄联盟)补丁的内容。这说起来容易,但是执行起来却是一个充满挑战的任务。

今天,我们讨论实现这一目标我们所铺设的基础:Riot 游戏数据服务器(GDS)。虽然这是一篇技术文章,但是我会站在一个较高的层次来解释这个问题。如果你是一个在做多系统间传送数据工作的工程师,我希望这能让你特别感兴趣。

游戏数据

首先,我们了解一些背景。在LoL的工作中,存在两种类型的游戏数据:一种是 key-value 对,被称为属性数据(如 Black Cleaver HP 奖金是300),另一种是不透明的二进制数据(如,大文本、动画和视频)。在这篇文章中,我们只讨论属性数据,二进制数据处理是未来潜在的一篇博文。

在LoL的所有历史中,属性数据由一堆松散、混乱的文件组成,这些文件存储在一个大的名为 DATA 的文件夹中。

早期,我们将数据存储在.ini的文件中(对,就是 Windows 下 .ini的文件格式)。类似如下所示:

没有漂亮的界面

当然,我创建这个例子是为了强调一些我们在编辑.ini文件时遇到的一些共同的问题。这离用户友的界面相差甚远。编辑原始文本时非常容易混乱——缺乏重要的内容,而其他字段又重复。设计者们每天不得不处理这种混乱,这里总共有 977 种法术,这些功能(当然忽略)位于“MissileEffect=AnnieBasicAttack_mis.troy”行中,在很早的LoL开发中,每个冠军涉及一个令人愉快的场景:“Death=Cardmaster_Death.wav。”

下面是当前数据系统面临的一些关键问题:

使用 Notepad++ 来编辑属性数据
对已存在的字段没有清晰的定义
缺乏类型安全
多人同时编辑同一个文件时会有合并冲突问题
繁琐的并行版本(活跃(Live)版、公测版(PBE)及内部版本)
松散的文件链接;只有短名称和隐藏的搜索路径

游戏数据服务器

我们特意设计一个游戏数据服务器系统来定位这些问题。最基础的是 RiotGameDataServer.exe——一段运行在每个开发者机器上的小程序。它以一个 Riot 拳头形式显示在工具栏,它所做的工作是连接属性数据与计算机上的程序

准备着的GDS

GDS 为其他工具抽取出文件和数据的管理方式,所以这些工具只需要关注传送过来数据的展示和编辑。我将其类比于操作系统窗口创建的抽象来思考,所以一个开发者只需要关注窗口该如何显示即可。GDS 工具还包括许多内部开发工具,也有第三方工具,如 Maya 和 Photoshop。它们都通过基于 JSON 格式数据的 RPC API 与 GDS 进行通信。

关于一份整洁的 RPC API,我们可以很容易的通过使用一个名为Swagger的标准来生成一个文档页,它列出了所有的有效函数。这是 GDS 暴露的一小部分函数子集:

Swagger 文档

GDS 属性数据存在一个名叫 PROPERTIES 的文件夹中。该文件夹最终将包含所有英雄联盟的属性数据。当一个工具需要识别出在什么情况下 Black Cleaver 是 Pantheon 最喜欢的武器时,它就会给 localhost:1300(GDS 监听的端口)发一个 HTTP 请求。当接收到一个“get?path=Items/BlackCleaver”请求时,GDS 就会去 PROPERTIES/Items/BlackCleaver.json文件中查找。响应结果类似如下所示:

稍微漂亮一点

当某个工具想要改变 Black Cleaver 造成的伤害值时,该工具需要发送另一条命令到localhost(或 127.0.0.1)的 1300 端口上,这次需要发送的指令是“et&path=PROPERTIES/Items/BlackCleaver.FlatHPMod&value=1000.”。GDS 工具将从源码控制工具(Perforce)中获取到指定的文件,并编辑对应的值,然后将成功或失败的结果返回给页面。因此,任何工具都可以很简单的修改属性数据文件,而不需要考虑数据的格式,文件操作或者其他复杂的因素。

这样,我们就很容易创建工具,如RiotEditor,来解决问题 #1:使用 Notepad++ 来编辑属性数据。

现在,我们总算有点结果了

属性标记

对任何给定的类型,非常重要的一点是识别出其实际在的字段,这样我们才能知道用户可以编辑什么。为了完成这项工作,我们维护了一个环环相扣的宏与magic 模板集合,该集合允许我们在工程代码里面直接标注类型。大概形式如下所示:

宏的修改

注意宏:PROPERTY_CLASS,PROPERTY_START,PROPERTY及 PROPERTY_END。它们负责两项主要任务:

告知类定义了哪些出口,类的哪些字段应该是可编辑的。

告知属性加载系统内存的偏移量,以便在运行时载入属性值。

PROPERTY 宏可通过特定的简单模板函数自动推断类型。我们可以引用复杂类型,如BoundingVolume,只需要提供它们拥有的子属性的标注。我们也可以跳过某些字段,如mRuntimeNumber,这意味着它们不会在 GDS 中暴露出来。

这是 GDS 中使用的 JSON 定义的结果:

Aww yiss

属性标记解决了问题 #2 和 #3:分别是对已存在的字段没有清晰的定义和没有类型安全。

GDS 除了为其他工具抽取出文件和数据的管理方式外,还做了一件相当酷的事情,就是为 Riot 开发工程师提供一项技术,我们称之为“层”。手游账号拍卖一层代表了一个可以关闭或打开的功能,我们可以为一个新的冠军,一种新皮肤,一个游戏模型或一次大的重新平衡创建一个层。然后,当一个内容创建者在某一功能上工作时,他们可以告诉 GDS,例如,“激活”APItemRework层。

之后,GDS 会对APItemRework层包含的文件任何改变打上标签。在磁盘上,这看起来像一个文件,我们称之为RabadonsDeathcap.json,挨着该文件的另一个文件,名为RabadonsDeathcap.APItemRework.json。在第二个层文件中,GDS 简单的标记每个被改变的字段为 delta。保存前后两个值就是为了解决之后的合并冲突。这两个文件并排看起来如下所示:

左侧:基础数据;右侧:delta 层

由于我们捕获了单个字段的改变,我们不再需要担心多个 Rioters 同时修改同一个文件了,除非他们修改完全相同的字段。如果他们修改了同一个字段,我们也存储了修改前后的值,所以可以识别出冲突。这样做的好处是可以防止一个发包以后的bug:在创建 DJ Sona,团队意外的将其状态恢复到了上一个版本。

现在,我们解决了问题 #4:多人同时编辑同一个文件时的合并冲突问题。

分层,让我们捕获了某一特定功能的所有改变。为了真正发布这些功能,我们需要引入一个概念,叫做“游戏版本”。一个游戏版本定义了一个完整的打开层的集合。每个游戏版本保存了一个层名称的简单 JSON 列表。在任何给定的时间点,我们维护几个主要的游戏版本:

Alpha:内部测试、准备发布到公测服务器上的功能集合。

Beta:当前公测服务器上的功能集合,如Jhin。要注意的是,Beta 版继承了 Release 版的功能列表,所以它拥有最近更新的功能,类似于季前赛。

Release:当前正式服务器上的功能集合,如闪亮新补丁包 6.3。

还有一个很酷的特性是一个功能从一个版本迁移到另一版本只需要在我们层管理窗口执行一次拖拽操作即可,有了这个以后,我们不再需要在某个功能发生改变时,需将成百上千个文件从一个地方拖到另一个地方了。

这样就很容易解决了问题 #5:全文件覆盖的并发版本(活跃版、公测版及内部版本)

总结

希望这篇文章能让你体会到我们是如何使得LoL开发更有效率的。对于细心的读者,你可能发现我们没有深入讨论问题 #6:松散的文件链接;只有短名称和隐藏的搜索路径。我留下这个问题没解决是因为这个问题比预期的更麻烦——存在冗余、避免不必要的代码重构、增加数据迁移、补丁大小等问题,因此,值得专门为此写一篇完整的博客。

如果你对我们如何改变英雄联盟中混乱的游戏数据的某方面感兴趣,请务必在评论中告知我们。

揭秘《英雄联盟》的游戏数据服务器相关推荐

  1. 揭秘英雄联盟的数据服务器

    揭秘英雄联盟的数据服务器 Hey,大家好!我是 Bill "LtRandolph" Clark,一名英雄联盟的游戏工程师.许多 Rioter 工程师关注大量的内容需要直接发送给玩家 ...

  2. web网页设计期末课程大作业~超高仿英雄联盟LOL游戏官网设计与实现(HTML+CSS+JavaScript)...

    仿英雄联盟LOL游戏官网设计与实现(HTML+CSS+JavaScript) 关于HTML期末网页制作,大作业A+水平 ~游戏网页作业HTML+CSS+JavaScript实现,共有游戏首页 等页面! ...

  3. 美服lol服务器位置,英雄联盟:LOL四大服务器王者常用位置分析,国服野爹盛行...

    原标题:英雄联盟:LOL四大服务器王者常用位置分析,国服野爹盛行 全球总决赛本周将进入淘汰赛阶段,这也意味着S9进入了尾声,想必有很多撸友好奇王者们都是打哪个位置成功进入王者段位的吧?本文将对大家介绍 ...

  4. 英雄联盟修复返回服务器异常,玩LOL英雄联盟在XP中服务器连接异常退出的恢复步骤...

    LOL英雄联盟是很多的喜欢网友的小伙伴在安装的游戏软件,对于一些电脑配置低的可以玩的不是很顺畅的,有小伙伴在XP系统的电脑中安装了LOL英雄联盟以后出错服务器连接异常不能登录的情况,遇到这样的问题我们 ...

  5. 机器学习算法(七): 基于LightGBM的分类预测(基于英雄联盟10分钟数据判断红蓝方胜负)

    机器学习算法(七)基于LightGBM的分类预测 1. 实验室介绍 1.1 LightGBM的介绍 LightGBM是2017年由微软推出的可扩展机器学习系统,是微软旗下DMKT的一个开源项目,由20 ...

  6. win7英雄联盟登陆显示无法连接服务器,如何解决Win7玩英雄联盟无法连接到服务器...

    英雄联盟(lol)是目前很火热的一款3D电子竞技类网游,那么如何解决Win7玩英雄联盟无法连接到服务器呢?学习啦小编分享了解决Win7玩英雄联盟无法连接到服务器的方法,希望对大家有所帮助. 解决Win ...

  7. python游戏代码怎样才能玩好英雄联盟_用Python编写代码分析《英雄联盟》游戏胜利的最重要因素...

    原标题:用Python编写代码分析<英雄联盟>游戏胜利的最重要因素 点击上图查看 Python Web 开发入门实战[教学大纲+教学进度表] 介绍 在过去的几年里,电子竞技社区发展迅速,曾 ...

  8. 计算机无法使用网络连接到服务器,Win7系统电脑玩英雄联盟无法连接到服务器的原因及解决办法(六种解决办法)...

    对于现在的网络游戏英雄联盟来说,是(简称LOL)的一款游戏,也是目前很火热的一款3D电子竞技类网游,而且现在也有很多玩家都喜欢玩这个游戏.可是最近却有Win7系统用户反映,自己正想打开LOL玩的时候, ...

  9. 英雄联盟男爵领域服务器位置,男爵领域或取代艾欧尼亚?回顾LOL各大区发展史...

    [摘要]随着全网通大区"男爵领域"的开启,英雄联盟的服务器再一次的迈向了一个全新的开始 从寥寥无几的电信网通大区,再到百花齐放的各类大区,最后到如今的全网通大区,跟游戏的发展一样, ...

最新文章

  1. 浏览器标准模式与怪异模式的区别
  2. 听说最近你读过不少书
  3. [register]-TCR(Translation Control Register)寄存器详解
  4. python打开excel数据库_使用python导入excel文件中的mssql数据库数据
  5. 架构日趋复杂的今天,如何重构数据库和应用边界?
  6. 如何绘制高大上的词云图?
  7. 20. javacript高级程序设计-JSON
  8. 梦幻西游易语言辅助教程
  9. __raw_writel, writel_relaxed 和 writel的区别
  10. 腾讯java校招,09.26 腾讯校招前端一面经历
  11. uniapp启动页面
  12. 如何区别聚合支付“一清二清”?
  13. 常见数据收集网站-数学建模(二十二)
  14. 小程序通过摄像头拍摄个人身份证
  15. matlab确定分段函数的间断点,凡分段函数必有间断点
  16. C1083: 无法打开包括文件: plugin.moc: No such file or directory
  17. 1560_AURIX_TC275_NMI Trap以及PMC
  18. 笔记本损耗60 计算机提示,笔记本电脑寿命短,你可能犯了这3个错误
  19. python raise函数
  20. 3010基于二叉链表的二叉树高度的计算

热门文章

  1. 开箱即用!中文关键词抽取(Keyphrase Extraction),基于LDA与PageRank(TextRank, TPR, Salience Rank, Single TPR)
  2. 天津市雏鹰企业认定奖励及申报标准介绍,补贴5万
  3. Content Size Fitter组件的使用
  4. 3.Jenkins入门基础使用与Maven+SonarQube集成配置与实践
  5. 解决报错:The Module Root specified is not a module according to Intellij
  6. 高通发布骁龙 695、778G+、480+、680 4G 四款芯片
  7. MySQL创建数据库和表格
  8. Matplotlib——饼图pie()函数
  9. 中国创业的孵化器和加速器
  10. 父类与子类的执行顺序