如何制作一个MMO(服务器端)?

8

我曾尝试搜索如何制作MMO,并且总是找到相同的回复,即它是不可能的或需要大量资金,但从未给出制作指南。

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


组件:

  • 登录服务器:客户端向该服务器发送用户名和密码,如果成功,则提供要连接的游戏服务器。
  • 游戏服务器[1..N]:所有游戏逻辑都在此处,客户端连接到此服务器。
  • 位置数据库:存储当前已登录用户和活动怪物的数据,在哪个游戏服务器上,他们在地图上的位置以及他们正在进行的操作(移动、攻击等)。
  • 帐户数据数据库:存储有关用户的所有数据(用户名、密码、角色、物品、任务等)
  • 聊天服务器:由于在同一位置的用户可能在不同的服务器上,因此需要额外的服务器,以便玩家可以彼此通信。
  • 怪物数据库:包含所有怪物的属性、基本位置和AI脚本的数据库。
  • 怪物服务器[1..N]:服务器中的所有活动怪物
  • 日志数据库:存储所有采取的操作和聊天文本。

操作:

  • 登录:
    1. 客户端向登录服务器发送用户名和密码。
    2. 登录服务器验证帐户数据库中的数据,并检查该用户当前是否已登录(位置数据库),如果成功,则转到3,否则返回失败的登录消息。
    3. 登录服务器更新位置数据库,将新连接的用户添加到他将连接的服务器(人数最少/最近)中。
    4. 位置数据库通知相应的游戏服务器用户已连接。
    5. 登录服务器向客户端发送所连接的游戏服务器。
  • 主循环(客户端):
    1. 客户端在位置数据库中检查自己的当前位置和操作,以及那些接近他的人(玩家和怪物),接收到的数据还包括玩家上次更新的时间(齿轮或等级)。
    2. 客户端比较收到的玩家日期与当前保存在内存中的玩家日期,如果该玩家不在内存中或者日期不同,则客户端请求帐户数据库获取等级、齿轮等信息。
    3. 客户端渲染玩家。
    4. 一段时间后返回1。
  • 聊天:
    1. 客户端向聊天服务器发送消息(私人/普通/全部)。
    2. 如果是私人,聊天服务器将消息发送给目标。
    3. 如果是普通,聊天服务器与位置服务器检查该区域的玩家(与主循环(客户端)中检查接近玩家的玩家相同)并将消息发送给这些玩家。
    4. 如果是全部,聊天服务器广播给所有玩家。
    5. 确认发送方和接收方都已收到消息。
  • 操作:
    1. 客户端向游戏服务器发送操作(制作、移动、攻击等)。
    2. 游戏服务器处理操作,并将操作的影响更新到位置数据库中(客户端将知道主循环操作发生了什么)。
    3. 在制作或拾取物品的情况下,游戏服务器将获得的物品返回给客户端。
  • 主循环(游戏服务器):
    1. 检查来自客户端的所有接收数据并对其进行处理。
    2. 向客户端发送处理结果(伤害、经验值、获得的物品等),并将其效果更新到位置数据库中(新位置等)。
    3. 一段时间后返回1。
  • 主循环(怪物服务器):
    1. 检查是否有玩家靠近活动怪物,如果没有,则从怪物服务器和位置数据库中删除它。
    2. 检查位置数据库中的所有玩家是否有任何接近的怪物(来自怪物数据库)并且未激活,并将其激活(更新位置服务器和怪物服务器)。
    3. 怪物根据存储在怪物数据库中的脚本采取行动(攻击、移动、不做任何事情等)。
    4. 一段时间后返回1。

我有以下问题:

  1. 这种实现方式是否可行?(考虑到有大量怪物和玩家的大地图)
  2. 我感觉如果事情变得更加复杂,位置数据库会承受很大的压力。最好的方法是:
    • 建立多个位置数据库
    • 建立一个链接(玩家/怪物,游戏服务器,位置数据库)的数据库
    • 建立一个链接(位置数据库,区域)的数据库
    • 这样一个位置数据库就是基于一个区域(或几个区域),当一个玩家移动到另一个区域时,他的数据就会被转移到另一个位置数据库中;最后一个数据库(位置数据库,区域)是为了防止一个区域有太多玩家而几个位置数据库可以共享同一区域(如果某些区域的人不多,则一个位置数据库可以承载一些区域)
  3. 关于使用的技术,我正在考虑以下内容:
    • 登录服务器:scala/django
    • 游戏服务器:C++原始编程?
    • 位置数据库:scala/django用于通信和带有SQL的数据库
    • 账户数据库:scala/django用于通信和数据库,不确定是否使用像mongoDB这样的NoSQL,还是将账户保存在文件上(哪种更好?)
    • 聊天服务器:C++原始编程,还是应该尝试适应IRC服务器?
    • 怪物数据库:SQL
    • 怪物服务器:像游戏服务器一样
    • 日志数据库:SQL
  4. 客户端和服务器之间的通信应该使用UDP以实现更快的通信?登录时使用TCP?或者应该始终保持一个开放的TCP套接字连接客户端和服务器?以及对于聊天,是TCP还是UDP?
  5. 主循环大约每多少时间运行一次可以使游戏顺畅进行?每0.5秒,0.1秒,接近60fps的时间?另外,为了创建计时器,抛出线程比较好?(控制线程的数量,因此如果循环所需时间超过预计时间)

投票关闭...但我认为你已经有了一个不错的开端。这就是我会做的,除了我会使用不同的编程语言。不过这纯粹是个人喜好。 - Corey Ogburn
不要一开始就尝试制作一个大型多人在线游戏,而是先尝试制作一个简单的双人游戏,比如石头剪刀布或者纸牌游戏,并且完整地包含大厅、匹配等功能。一旦你完成了这个项目,你将会有更多经验来开始制作一个大型多人在线游戏。 - AndresQ
我已经制作了一款纸牌游戏(用于我的大学毕业项目),其中包括了TCP/IP,最多可供8名玩家使用(由于是回合制游戏,因此编程非常简单),所以现在我想尝试构建一个MMO。但问题在于没有关于如何开始的指南,因此我将我的想法放在如何建立通信基础等方面(我知道逻辑也需要很多工作)。 - user1090694
2个回答

5
我认为你的解决方案无法扩展。问题在于你的位置数据库需要针对每个玩家操作进行更新。你可能使用这种方法来允许游戏服务器共享数据,但这是一个不好的想法,因为数据库并不意味着要启用系统分发。将数据库视为真正的离线存储,只有在玩家或对象被激活时才能加载状态。
你需要摆脱位置数据库,并将玩家状态分布在游戏服务器之间存储。
还要考虑拥有一个前端服务器,始终保持与客户端的连接,将信息传递到正确的游戏服务器等。通过这种方式,你可以避免客户端连接到“正确”的游戏服务器以及所有伴随该级别信任的问题。
分布式编程相当困难,但是编程语言Erlang比Python/C++等更容易做到。

2

Christian说得对,你过于依赖数据库了。通常游戏和玩家的当前状态在运行时存储在实际服务器中。你可以制作一个功能,自动更新玩家位置或状态的数据库,这在大型多人在线游戏中非常普遍,但最终数据库只是在启动时获取数据的参考,而不是在运行时。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接