延续新伊甸的记忆
作为“宇宙进化”计划的一部分,我们仍在持续推进EVE Online客户端和服务器从Python 2向Python 3的升级。这项工作对于夯实游戏未来发展的技术基础至关重要,也将为未来多年的持续开发做好准备。
国家档案所
本期《宇宙进化》深入探讨了NPC代理人的记忆机制,包括它如何处理每天约10万份任务的记录与管理,以及这一机制所带来的种种有趣挑战,而这些挑战未来可能会对玩家产生影响。
在本文中,“代理人”是指EVE中的NPC代理人:这些可爱的角色有时会不太客气地要求你把垃圾运到另一个空间站、消灭最新出现的海盗威胁,或者再次拯救那个可怜的落难少女,而作为回报,你会获得相应的奖励。

先说重点
因为大家都喜欢深入的技术分析,所以我们很快就会提到非常具体的内容。不过,如果你只想快速了解重点,不妨先浏览以下摘要:
随着EVE Online升级至Python 3并实现现代化,NPC代理人的数据存储方式也需要进行调整。我们将在后台对任务以及玩家与代理人的其他互动追踪方式进行升级。这意味着需要清理一部分旧数据,并将剩余数据转换为更具前瞻性的数据格式。
这个过程基本上不会被玩家察觉。唯一可能明显受到影响的,是2026年9月29日之前保存的旧任务进度。
你的NPC声望不会受到影响。即使你没有登录游戏,或当前并非欧米伽克隆状态,你已经解锁的任何代理人仍将继续可用。你不会丢失任何进度。
从今天开始,如果你向代理人领取新任务(或现有任务完成/失败),该任务进度现在会自动转入新的记忆中。
如果你在今天之前与某位代理人有过互动,而今天之后不再与之互动以更新相关进度,那么当Python 3迁移工作完全结束后,该代理人的相关任务将被清除并删除。
目前我们还无法确定具体的清理时间,因为这只是庞大的Python 3迁移工作中的一环。整个迁移过程需要数月,而不是数天。随着清理时间临近,我们会提前提醒你,然后才会清除这些记忆。
如果你在今天之前有已提供/已接受的任务,并且在今天之后没有与代理人互动以完成该任务,那么未来某个时间点,这项任务的进度将被清除。
如果你在今天之前已经委托研究代理人获取研究点,那么今天之后,你需要至少与该代理人完成一次任务,才能让其保持活跃。(每个人物针对每名代理人只需完成一次即可。)最终,我们会清理所有自今天起就再也没有进行过互动的旧研究任务。
简而言之,如果你目前正在积极执行代理人任务,那就照常游戏即可,不会有任何变化。如果你有特别在意的代理人(尤其是研究代理人),那么不妨去拜访他们并完成一次任务,免得他们把你忘了。
现在你已经了解了基本情况,如果想进一步了解代理人的“囤积”习惯,以及一些尘封已久的秘密,那就继续往下看吧……
世界碰撞

要理解我们所说的“代理人记忆”,首先需要了解一些背景。整个Python 3项目大致可以分为以下几个部分:
运行时 - 让游戏运行的客户端和服务器可执行文件。
数据 - 构成EVE Online独特游戏体验的各种信息。这部分还可以进一步划分为:
内容数据- 模型、纹理、文字、属性以及艺术家、设计师和编剧们创造的其他一切内容。其中一部分数据会随客户端提供给玩家,另一部分则仅存储在于我们的服务器中。
网络数据 - 通过互联网在你的客户端与我们的服务器之间传输的信息数据包,以及数据中心服务器集群中
200
多个节点之间相互传输的数据包。
持久化数据 - 不断增长的“存档文件”,记录着游戏20多年来积累的玩家成长与游戏进度。其核心就是位于EVE核心的大型SQL数据库。代理人的记忆就存储在这里。
开发者生态系统 - 我们开发者日常使用的工具和流程,用于不断为玩家呈现游戏内容。
探究代理人的记忆
既然我们知道了记忆存储在哪里,我们就可以讨论它究竟是什么了。每当你的角色与某名NPC代理人互动时,我们都会将这次互动记录到数据库中。互动方式可能包括:领取新任务、完成(或失败)之前接受的任务、开始研究任务或定位任务,或者获得特殊剧情代理人的推荐。
每名代理人都知道自己与曾经交谈过的每个人物的上次互动状态。也就是说,假如你在20年前曾经拜访某位代理人,接下了一项寻找可疑全息记忆盘的任务,那么这个代理人至今仍然记得你,而且还在等着告诉你:你没能在合理的时间内完成任务!
代理人可能会保存与你的人物相关的以下记忆:
他们给你布置了哪些任务,以及这些任务目前的状态(例如:目标
NPC是否已经被消灭)
如果代理人正在执行研究任务,目前的进展如何
如果你曾委托代理人寻找另一个人物,目前的进度如何
你在剧情任务链中推进到了哪一步你完成过哪些史诗剧情线或职业任务
需要注意的是,NPC人物/军团与你的人物之间的声望关系并不属于代理人的记忆。声望是独立的机制,有自己单独的状态追踪方式。
获取数据资料
最后,我们来看看这些数据究竟是如何存储和读取的,以及我们撰写这篇博客的原因。
早在21世纪初,EVE Online即将正式上线的时候,我们就已经开始设计代理人记忆数据库了。当时的需求是存储代理人与人物之间互动所形成的复杂状态。在数据库设计中,我们通常会尝试为这类数据建立非常规范的表结构和关系模型。但代理人的记忆需求既混乱又动态——每次互动涉及的变量集合都大不相同(比如,描述一项运输任务和一次剧情代理人推荐,它们所需的数据显然完全不同),更何况,随着游戏不断发展,相关设计也在快速变化。
而在那个年代,现代NoSQL运动尚未开始。EVE当时坚定地使用MSSQL作为持久化存储层。一名聪明的程序员想到,可以将保存代理人记忆的Python对象序列化为二进制数据块,再将这个数据块作为文本存储在数据库表中。
之后,当角色再次与代理人互动和唤醒代理人时,过程就反过来了:系统从数据库中读取该代理人的二进制数据块,将其反序列化,还原成Python对象,然后注入正在运行的代理人中,从而恢复它的记忆。(在Python中,这个过程也称为序列化和反序列化。)
虽然这种方式很好地解决了当时面临的问题,但也为未来埋下了两个隐患:
记忆数据块很难进行搜索。数据库的强大之处就在于搜索——例如,找出某个参数具有特定值的所有记录。但每份记忆都被封装在一个Python“外壳”里,意味着我们无法高效查询其中的具体内容。比如,要找出与前面提到的落难少女有关的所有记忆,就必须把每一份记忆逐个加载到Python中,再检查其中的内容。显然,这种做法并不理想。
数据格式与所使用的Python版本绑定在一起。随着Python语言不断发展,新功能不断加入,一些旧功能则逐渐被弃用,最终甚至被彻底移除。这意味着到了某个时候,这些记忆将变得无法读取——
就像融入雨中的泪水一样,永远消失。随着从Python 2迁移到Python 3,这一天很快就会到来。
隐蔽的仓库
我们可以用一个通俗易懂的例子来解释这个问题:想象你搬家时需要把东西存进仓库。一种方法是将所有东西装进一个巨大的密封集装箱,然后把它送进仓库(这就是“序列化”你的数据)。这种方式很灵活(运集装箱的卡车并不会管里面装的是黑胶唱片还是CD),而且操作起来很快,集装箱运输本身也早已成为一种标准化流程。
等你搬进新家后,集装箱已经运到了你家,就可以打开箱子,取出那些珍贵的家当。不过,这种方式也有一个缺点:如果仓库需要进行安全检查,确保里面没有存放任何违禁品,那么唯一的办法就是人工打开并检查每一个集装箱。效率可想而知。
权宜之计
尽管这种做法存在长期弊端,但它确实奏效了。EVE Online顺利上线,并一路发展至今。代理人记忆系统也一直运行良好,经受住了时间的考验——至少从整体来看,表现相当不错。但没有什么东西能够持续长存。
清除记录
迁移到Python 3为我们提供了一个千载难逢的机会,让我们能够处理过去遗留的问题。我们需要摆脱将Python数据块存储在SQL数据库中的僵化方式,以及这种方式与生俱来的过时风险。与此同时,我们也借此机会进行一些整理工作,清理掉大量积压的数据。(代理人记忆表是我们数据库中最大的表之一,也是极少数只增不减的表之一。)
新旧格式并存
这项工作其实已经在幕后展开了。最近,我们更新了代理人记忆的加载和保存方式。现在,每当需要保存新的记忆时,我们都会同时以两种形式保存:
旧版的不透明Python数据块格式——完全沿用我们过去一直使用的方式。
面向未来的全新透明格式——不依赖特定的Python数据格式,同时也为更高效的搜索和未来的灵活调整留下了空间。
目前,所有新建或更新的记忆都会同时以这两种形式存在。如果你今天向代理人领取一项任务,这份记忆就会同时保存为两种格式。这样一来,我们可以自行选择在加载代理人记忆时优先使用哪一种格式。同时,这也能降低风险:在彻底关闭旧方法之前,我们可以先检查两种格式记录的内容是否一致,确保它们讲述的是同一个故事。
当我们需要从数据库中重新加载某个代理人的记忆时,现在有几种方式可以决定优先使用哪个数据源。整个过程将分为三个阶段:
第一阶段:初期,我们会继续只从旧版存储中加载数据,直到确认新格式能够正常运行。
第二阶段:随后我们会调整优先级,首先从新格式中寻找记忆;如果没有找到,再退回旧格式加载。
第三阶段:最后,当其他部分全部完成Python 3迁移后,我们将彻底停止从旧格式中读取数据。届时,代理人只能使用以新格式保存的记忆。然后,我们终于可以从数据库中删除那些从未更新过的旧版记忆,这样也可以减轻我们的数据库管理员的负担。
从今天开始,任何新产生的记忆都会随着我们一起迁移到Python 3的新系统中。这次迁移将是一个漫长的过程,所以你有充足的时间与代理人互动、领取新任务或完成现有任务。我们说的是几个月,不是几天。随着第三阶段临近,我们会及时告知大家。
必须保留的数据
有些记忆无论年代多么久远,我们都必须一并迁移,哪怕相关角色没有登录游戏,也没有与对应代理人互动来生成更新后的记忆。例如,某些教程任务或史诗剧情任务只能完成一次,因此我们必须记录玩家是否已经完成过这些任务。对于这些有限的特殊情况,我们会在后台自动将相关数据迁移到新格式。
声望是角色与代理人关系的一个重要组成部分。在你从1级代理人一路晋升到4级甚至5级代理人的这个过程中,你会一直积累声望。所有人物与NPC代理人、军团及势力之间的声望都会得到保留,不会受到这些改动的影响。我们不会重置或丢失这些声望。
持续进行中
Python 3迁移工作仍在继续。除了转换客户端和服务器代码这个“简单”的部分之外,围绕代码进行的各种更新工作同样繁重,甚至可能更加庞大。我们的开发人员每天使用的大量工具需要更新;Python进程通过网络与其他组件通信时存在的众多接口需要处理;还有部署流程——正是这些流程让我们能够按下一个按钮,就让一个资料片更新正式上线。
正如我们所见,即使是存储在数据库中的数据,有时也需要进行一些刷新。
一路顺风,我们下篇博客再见。
