如何自动更新在线游戏客户端

在本文中,我将讨论如何为在线客户端游戏创建自动更新系统。 链接到文章末尾的源代码(Delphi)。 实际上,我在两款游戏中都实现了此功能,如果第一个煎饼显得有些笨拙(在Spectromancer游戏中),则第二个实现非常方便和有效。 这是我关于哈布雷的第一篇文章,所以不要费劲,而要指出评论中的缺陷:)

游戏更新算法


  • 检查版本以进行更新。
  • 下载当前版本的文件列表。
  • 将新文件或更改的文件下载到临时文件夹。
  • 安装更新-按照列表显示已安装客户端的文件。
  • 启动更新的客户端。

版本检查


首先,在启动时,客户端会向服务器询问当前版本的数量(X)和不更新而允许的最小数量(Y)。 如果客户端版本不低于Y,则不需要更新,否则客户端将启动更新实用程序“ GetNewVersion.exe X ”,并自行关闭。

如您所见,版本号由参数传递-这使您可以将游戏更新到服务器上可用的任何版本,甚至降低版本。 如果未传递参数,则实用程序本身将向服务器请求当前版本号。 版本号只是一个整数,编号方案可以是任何编号,例如,我的版本1.12对应于编号1120。

服务器的响应不会立即出现,在我们收到响应之前,我们无法创建游戏窗口,因为您可能必须立即关闭它,并且屏幕上无法理解的闪烁根本不是我们所需要的。 响应超时将需要一些时间,并且客户端正忙于加载/解压缩最重的JPEG。 您也不能等待太久:玩家启动了游戏-但屏幕上什么也没有发生,一团糟。 因此,如果在1.0秒内。 服务器未收到响应-以常规方式继续加载游戏。 没什么大不了的:玩家尝试登录服务器后,他会收到一条消息,提示需要更新客户端,或者服务器不可用。

下载文件清单


知道版本号后,更新实用程序[base_ur]>/[]/filelist下载文件列表: [base_ur]>/[]/filelist
这只是带有校验和,压缩大小和未压缩大小的CSV文件的列表,每行看起来像这样:
18*Priest.tga;1053151921D9;91719;107372
这里的“ 18 *”表示文件名中的18个字符与先前的文件相同。 由于文件通常按字母顺序排列,并且路径可能很长-这大大节省了列表文件的大小。 对于未启用压缩的Web服务器,这意味着文件下载速度更快,更新将更早开始。

下载新文件或更改的文件


我们不知道游戏客户端的年龄,也许某些文件已被手动更改或删除。 我们不想下载太多,因此,在收到文件列表后,该实用程序将开始检查文件以进行更新:如果游戏文件夹中缺少该文件或其校验和不同,则该文件会添加到下载队列中。 同时,最多只能加载2个文件-这足够了,因此一方面下载不会减慢速度,但是另一方面,下载是顺序进行的。



一个特殊的主题是进度的显示。 在处理完整个列表之前,我们不确切知道要下载多少文件以及它们的大小。 但是,第一个文件上传后,我们就可以显示一些信息。 实际上,进度会显示下载队列:要下载的数量和已经下载的数量。

下载的文件会立即解压并保存在一个临时文件夹中,我使用zlib库进行压缩。

处理完整个文件列表并且完成所有下载后,该实用程序将检查是否存在changes.txt文件,如果存在,则显示该文件。 提示用户开始更新过程。 在点击“更新”按钮之前,尚未对游戏文件夹进行任何更改,因此您可以选择退出而不会出现任何问题。

顺便说一句,如果用户中断下载或拒绝安装,则下次无需再次下载所有文件:在下载下一个文件之前,该实用程序将检查临时文件夹中的文件存在,如果校验和匹配,则认为下载成功。



但是,当您单击“更新”时,该实用程序会启动另一个实用程序-“ InstallUpdate.exe ”,然后它会自行关闭。

安装更新


为什么需要其他实用程序? 很简单:要更新游戏文件,您需要以管理员权限运行。 但是相反,禁止下载更新。 因为,除非您是EV代码签名证书的满意所有者,否则以管理员权限启动该过程将显示UAC窗口。 并且,如果在开始游戏时,而不是通常的界面,玩家看到了以下内容:



...那么至少这是提防甚至完全放弃发射的原因。 另一件事,在手动同意安装更新的情况下-在这种情况下,通常会看到UAC窗口。 不幸的是,Windows中的进程无法在运行时提升其权限-此属性自启动以来一直未更改。 因此,我使用两个单独的文件。 实际上, GetNewVersion.exeInstallUpdate.exe是相同的实用程序,文件是相同的。 动作由传输的参数和可执行文件的名称决定。

因此,在启动后,InstallUpdate将游戏客户端文件从临时文件夹复制到游戏文件夹,然后启动更新的客户端并终止。 在这种情况下, GetNewVersion.exe文件也可以被更新。

所有操作以及发生的错误都将详细记录在日志中;这对于调试非常有用。

准备新版本的过程


我们从游戏客户端的角度检查了更新操作方案,但是如何使其全部起作用? 为了准备新版本,我编写了另一个实用程序-CompressBuild 。 它递归扫描文件夹,使用Deflate方法压缩文件,然后将有关它们的信息写入文件列表filelist 。 压缩后,在文件名后附加符号“ _”。 压缩文件不会再次压缩,因此,如有必要,只能在构建文件夹中更新单个文件,CompressBuild仅会更新它们。

游戏客户端中的某些文件在操作过程中会发生变化,例如,包含设置。 必须忽略此类文件,该实用程序将从排除文件中获取适当的模板。 也就是说,这些文件根本不会进入filelist并且在更新时不会破坏客户端。

因此,为了准备一个新版本,我需要:

1.将\master文件夹复制到\[_]
2.运行CompressBuild ,它将打包文件并列出其中。
3.将所有内容上传到游戏的网站。
4.在游戏服务器上,将当前版本的编号更改为刚刚下载的编号。 瞧!

从现在开始,更新时人们将收到一个新版本。

好了,可以删除服务器上旧版本的文件夹,以免占用空间。

结论


当然,我的更新系统不是完美的,也不是没有缺陷。 例如,如果在客户端中删除了文件,则文件将保留在播放器中。 如果文件已重命名,它将作为新文件下载,而旧实例将不会被删除。 当然,您可以通过添加命令来删除/重命名文件到文件列表中来优化更新实用程序,但是总的来说,此类问题与我的游戏无关,因此我没有理会。

好吧,您可以在这里获取源代码: astralheroes.com/files/UpdaterSrc.zip
(在Delphi-2006 / Turbo Delphi中编译,我不能担保其他编译器)。

Source: https://habr.com/ru/post/zh-CN423207/


All Articles