8

我曾尝试搜索有关如何制作 MMO 并始终找到相同的回复,这是不可能的或需要很多钱,但从未提供有关如何制作的指南。

我想构建一些非常可扩展的东西,我目前关于如何构建 MMO 的想法如下:


成分:

  • 登录服务器:客户端向该服务器发送用户名和密码,如果成功,则向客户端提供要连接的游戏服务器。
  • 游戏服务器[1..N]:所有游戏逻辑都在这里,客户端连接到这个。
  • 位置数据库:存储当前登录的用户和活动怪物的数据,他们在哪个游戏服务器,他们在地图上的位置和他们采取的行动(移动,攻击等)。
  • 帐户数据数据库:存储有关用户的所有数据(用户名、密码、字符、项目、任务等)
  • 聊天服务器:由于同一个地方的用户可以在不同的服务器上,所以需要多做一个,以便玩家之间进行交流。
  • Monster DB:一个包含所有怪物属性、基地位置和AI脚本的数据库。
  • Monster Server [1..N]:服务器内所有活跃的怪物
  • 日志数据库:存储所有采取的行动和聊天文本。

行动:

  • 登录:
    1. 客户端将用户名和密码发送到登录服务器。
    2. 登录服务器使用Account Data DB验证数据并检查当前未记录的(Position DB),如果成功则转到3,如果不成功,则发回不成功的登录消息。
    3. 登录服务器更新位置数据库,将新连接的用户添加到他将连接的服务器(人数最少/最近)
    4. Position DB 通知相应的游戏服务器用户已连接。
    5. 登录服务器将游戏服务器连接到的客户端发送到客户端。
  • 主循环(客户端):
    1. 客户端在位置数据库中检查他当前的位置和动作以及他附近的人(玩家和怪物),在收到的数据中还包括玩家的最后更新时间(齿轮或等级)。
    2. 客户端将接收到的玩家的日期与当前保存在内存中的玩家进行比较,如果玩家不在内存中或日期不一样,客户会询问账户数据数据库以获得 lvl、齿轮等。
    3. 客户端渲染玩家
    4. 一段时间后转到1。
  • 聊天:
    1. 客户端向聊天服务器发送消息(pm/normal/all)
    2. 如果是 pm,Chat Server 将消息发送到目标
    3. 如果正常,聊天服务器会与位置服务器检查该区域中的玩家(与主循环(客户端)相同。1 当检查附近的玩家时)并将消息发送给这些玩家。
    4. 如果全部,聊天服务器向所有玩家广播
    5. 确认发件人和收件人收到邮件
  • 行动:
    1. 客户端向游戏服务器发送动作(制作、移动、攻击等)。
    2. 游戏服务器处理动作并使用动作效果更新位置数据库(客户端将知道主循环动作发生了什么)。
    3. 在制作或抢劫的情况下,游戏服务器将获得的物品返回给客户端。
  • 主循环(游戏服务器):
    1. 检查所有从客户端接收的数据并处理它们。
    2. 向客户端发送处理结果(伤害、经验、获得的物品等)并使用其效果(新位置等)更新位置数据库。
    3. 一段时间后转到 1。
  • 主循环(怪物服务器):
    1. 检查一个活跃的怪物附近是否有玩家,如果没有,则将其从怪物服务器和位置数据库中删除。
    2. 检查位置数据库中的所有玩家是否附近有任何怪物(来自怪物数据库)并且未激活并激活它(更新位置服务器和怪物服务器)。
    3. Monster 根据存储在 Monster DB 上的脚本采取行动(攻击、移动、什么都不做等)。
    4. 一段时间后转到 1。

以及我的问题:

  1. 这种实施方式会奏效吗?(考虑一张有很多怪物和玩家的大地图)
  2. 我有一种感觉,如果事情发展起来,Position DB 会非常紧张。如果:
    • 制作多个位置数据库
    • 创建一个链接数据库(玩家/怪物、游戏服务器、位置数据库)
    • 制作一个链接的数据库(位置数据库,区域)
    • 这样一个位置数据库基于一个区域(或多个区域),当玩家移动到另一个区域时,他的数据会移动到另一个位置数据库;最后一个 DB (Position DB, area) 是在一个区域有太多玩家的情况下,几个 Position DB 可以共享同一个区域(如果区域没有很多人,一个 Position DB 可以容纳一些区域)
  3. 关于使用的技术,我在考虑以下几点:
    • 登录服务器:scala/django
    • 游戏服务器:C++ 中的原始编程?
    • 定位 DB:scala/django 用于通信和 DB 与 SQL
    • 帐户数据数据库:用于通信的 scala/django 和数据库不确定是使用像 mongoDB 这样的 NoSQL 还是保存在文件中的帐户(这会更好吗?)
    • 聊天服务器:C++ 中的原始编程还是我应该尝试适应 IRC 服务器?
    • 怪物数据库:SQL
    • 怪物服务器:类似游戏服务器
    • 日志数据库:SQL
  4. 客户端-服务器之间的通信应该是 UDP 以便更快的通信?和 TCP 登录?还是应该在客户端和服务器之间始终保持打开的 TCP 套接字?另外,对于聊天,TCP 还是 UDP?
  5. 主循环应该每隔多长时间运行一次才能使游戏流畅运行?每 0.5 秒,0.1,接近 60fps?还让计时器会更好地在每个循环中抛出一个线程?(控制线程的数量,所以如果循环花费的时间比它应该的长)

而且我不认为我暂时忘记了任何要问的问题,并对这篇大文章感到抱歉……

4

2 回答 2

5

我认为您的解决方案不会扩展。问题是您的位置数据库,需要针对每个玩家操作进行更新。您可能使用这种方法来允许游戏服务器共享数据,这是一个坏主意,因为数据库并不意味着支持系统的分发。将数据库视为真正的离线存储,仅在激活玩家或对象时加载状态。

您需要摆脱位置数据库并存储分布在游戏服务器之间的玩家状态。

还可以考虑拥有一个始终与客户端保持一个连接的前端服务器,将消息中继到正确的游戏服务器等。通过这种方式,您可以避免客户端必须连接到“正确的”游戏服务器以及所有问题伴随着这种程度的信任。

分布式编程非常困难,但是编程语言 Erlang 比 Python/C++ 等更容易。

于 2013-12-28T20:04:36.590 回答
2

克里斯蒂安是对的,你太依赖数据库了。通常,游戏及其玩家的当前状态在运行时存储在实际服务器中。你可以做一个自动更新玩家位置或状态数据库的功能,这在 MMO 中很常见,但最终数据库只是在启动期间拉取数据的参考,而不是运行时。

于 2014-11-17T20:29:10.043 回答