我曾尝试搜索有关如何制作 MMO 并始终找到相同的回复,这是不可能的或需要很多钱,但从未提供有关如何制作的指南。
我想构建一些非常可扩展的东西,我目前关于如何构建 MMO 的想法如下:
成分:
- 登录服务器:客户端向该服务器发送用户名和密码,如果成功,则向客户端提供要连接的游戏服务器。
- 游戏服务器[1..N]:所有游戏逻辑都在这里,客户端连接到这个。
- 位置数据库:存储当前登录的用户和活动怪物的数据,他们在哪个游戏服务器,他们在地图上的位置和他们采取的行动(移动,攻击等)。
- 帐户数据数据库:存储有关用户的所有数据(用户名、密码、字符、项目、任务等)
- 聊天服务器:由于同一个地方的用户可以在不同的服务器上,所以需要多做一个,以便玩家之间进行交流。
- Monster DB:一个包含所有怪物属性、基地位置和AI脚本的数据库。
- Monster Server [1..N]:服务器内所有活跃的怪物
- 日志数据库:存储所有采取的行动和聊天文本。
行动:
- 登录:
- 客户端将用户名和密码发送到登录服务器。
- 登录服务器使用Account Data DB验证数据并检查当前未记录的(Position DB),如果成功则转到3,如果不成功,则发回不成功的登录消息。
- 登录服务器更新位置数据库,将新连接的用户添加到他将连接的服务器(人数最少/最近)
- Position DB 通知相应的游戏服务器用户已连接。
- 登录服务器将游戏服务器连接到的客户端发送到客户端。
- 主循环(客户端):
- 客户端在位置数据库中检查他当前的位置和动作以及他附近的人(玩家和怪物),在收到的数据中还包括玩家的最后更新时间(齿轮或等级)。
- 客户端将接收到的玩家的日期与当前保存在内存中的玩家进行比较,如果玩家不在内存中或日期不一样,客户会询问账户数据数据库以获得 lvl、齿轮等。
- 客户端渲染玩家
- 一段时间后转到1。
- 聊天:
- 客户端向聊天服务器发送消息(pm/normal/all)
- 如果是 pm,Chat Server 将消息发送到目标
- 如果正常,聊天服务器会与位置服务器检查该区域中的玩家(与主循环(客户端)相同。1 当检查附近的玩家时)并将消息发送给这些玩家。
- 如果全部,聊天服务器向所有玩家广播
- 确认发件人和收件人收到邮件
- 行动:
- 客户端向游戏服务器发送动作(制作、移动、攻击等)。
- 游戏服务器处理动作并使用动作效果更新位置数据库(客户端将知道主循环动作发生了什么)。
- 在制作或抢劫的情况下,游戏服务器将获得的物品返回给客户端。
- 主循环(游戏服务器):
- 检查所有从客户端接收的数据并处理它们。
- 向客户端发送处理结果(伤害、经验、获得的物品等)并使用其效果(新位置等)更新位置数据库。
- 一段时间后转到 1。
- 主循环(怪物服务器):
- 检查一个活跃的怪物附近是否有玩家,如果没有,则将其从怪物服务器和位置数据库中删除。
- 检查位置数据库中的所有玩家是否附近有任何怪物(来自怪物数据库)并且未激活并激活它(更新位置服务器和怪物服务器)。
- Monster 根据存储在 Monster DB 上的脚本采取行动(攻击、移动、什么都不做等)。
- 一段时间后转到 1。
以及我的问题:
- 这种实施方式会奏效吗?(考虑一张有很多怪物和玩家的大地图)
- 我有一种感觉,如果事情发展起来,Position DB 会非常紧张。如果:
- 制作多个位置数据库
- 创建一个链接数据库(玩家/怪物、游戏服务器、位置数据库)
- 制作一个链接的数据库(位置数据库,区域)
- 这样一个位置数据库基于一个区域(或多个区域),当玩家移动到另一个区域时,他的数据会移动到另一个位置数据库;最后一个 DB (Position DB, area) 是在一个区域有太多玩家的情况下,几个 Position DB 可以共享同一个区域(如果区域没有很多人,一个 Position DB 可以容纳一些区域)
- 关于使用的技术,我在考虑以下几点:
- 登录服务器:scala/django
- 游戏服务器:C++ 中的原始编程?
- 定位 DB:scala/django 用于通信和 DB 与 SQL
- 帐户数据数据库:用于通信的 scala/django 和数据库不确定是使用像 mongoDB 这样的 NoSQL 还是保存在文件中的帐户(这会更好吗?)
- 聊天服务器:C++ 中的原始编程还是我应该尝试适应 IRC 服务器?
- 怪物数据库:SQL
- 怪物服务器:类似游戏服务器
- 日志数据库:SQL
- 客户端-服务器之间的通信应该是 UDP 以便更快的通信?和 TCP 登录?还是应该在客户端和服务器之间始终保持打开的 TCP 套接字?另外,对于聊天,TCP 还是 UDP?
- 主循环应该每隔多长时间运行一次才能使游戏流畅运行?每 0.5 秒,0.1,接近 60fps?还让计时器会更好地在每个循环中抛出一个线程?(控制线程的数量,所以如果循环花费的时间比它应该的长)
而且我不认为我暂时忘记了任何要问的问题,并对这篇大文章感到抱歉……