Difference between revisions of "Zh:Protocol FAQ"
m (Kaniol moved page ZH:协议FAQ to ZH:Protocol FAQ) |
|||
Line 1: | Line 1: | ||
− | + | 人们总是会有一些关于Minecraft Modern [[ZH:Protocol|协议]]的问题,所以我们将在本文档中讲述其中一些最常见的。如果你仍有麻烦,在IRC上加入我们,[irc://irc.freenode.net/mcdevs irc.freenode.net上的频道#mcdevs]. | |
− | == | + | == 协议文档完备了吗? == |
− | + | 取决于你的定义,''是的''!所有的数据包类型都是已知的,而且已经记录了它们的布局。尽管丢失了一些小细节,但是你编写功能性程序所需的一切在这里都有。我们同样收集了[[ZH:pre-release protocol|预发布版]]更改的信息,这使得我们快速记载新的发布版。 | |
− | == | + | == 客户端的正常登入顺序是什么样的? == |
− | + | 有关与Mojang服务器的交流,见[[ZH:Authentication|认证]] | |
− | + | 推荐的登入流程看起来像这样,其中'''C'''是客户端而'''S'''是服务端: | |
− | # | + | # 客户端连接至服务端 |
− | # ''' | + | # '''C'''→'''S''': [[ZH:Protocol#Handshake|Handshake]] State=2 |
− | # ''' | + | # '''C'''→'''S''': [[ZH:Protocol#开始登入|开始登入]] |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#加密请求|加密请求]] |
− | # | + | # 客户端认证 |
− | # ''' | + | # '''C'''→'''S''': [[ZH:Protocol#加密响应|加密响应]] |
− | # | + | # 服务端认证,都启用了加密 |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#设置加密|设置加密]](可选的,启用加密) |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#登入成功|登入成功]] |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#加入游戏|加入游戏]] |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#插件消息(客户端方)|插件消息]]:带有服务端铭牌的[[ZH:Plugin channel#minecraft%3Abrand|<code>minecraft:brand</code>]](可选的) |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#服务端难度|服务端难度]](可选的) |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#玩家能力(客户端方)|玩家能力]](可选的) |
− | # ''' | + | # '''C'''→'''S''': [[ZH:Protocol#插件消息(服务端方)|插件消息]]:带有客户端铭牌的[[ZH:Plugin channel#minecraft%3Abrand|<code>minecraft:brand</code>]](可选的) |
− | # ''' | + | # '''C'''→'''S''': [[ZH:Protocol#客户端设置|客户端设置]] |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#手持物品改变(客户端方)|手持物品改变]] |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#声明配方|声明配方]] |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#标签|标签]] |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#实体状态|实体状态]] |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#声明命令|声明命令]] |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#解锁配方|解锁配方]] |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#玩家位置和外观(客户端方)|玩家位置和外观]] |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#玩家信息|玩家信息]](添加玩家动作) |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#玩家信息|玩家信息]](更新延迟动作) |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#更新视图位置|更新视图位置]] |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#更新光照|更新光照]](以玩家位置为中心的方形,每个区块发送一个) |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#区块数据|区块数据]](以玩家位置为中心的方形,每个区块发送一个) |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#世界边界|世界边界]](一旦世界结束加载) |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#生成位置|生成位置]](“家”生成,不是登入时客户端生成的位置) |
− | # ''' | + | # '''S'''→'''C''': [[ZH:Protocol#玩家位置和外观(客户端方)|玩家位置和外观]](必需的,告诉客户端已准备好生成) |
− | # ''' | + | # '''C'''→'''S''': [[ZH:Protocol#传送确认|传送确认]] |
− | # ''' | + | # '''C'''→'''S''': [[ZH:Protocol#玩家位置和外观(服务端方)|玩家位置和外观]](来确认生成位置) |
− | # ''' | + | # '''C'''→'''S''': [[ZH:Protocol#客户端状态|客户端状态]](在接受区块之前或之时发送,还需进一步测试,如果没有发送服务端也可正确处理) |
− | # ''' | + | # '''S'''→'''C''': 物品栏、实体等等 |
− | == | + | == 离线模式 == |
− | + | 如果服务端为离线模式,它不会发送[[ZH:Protocol#加密请求|加密请求]]数据包,相似地,客户端也不应发送[[ZH:Protocol#加密响应|加密响应]]。在这种情况下,从不会启用加密,也不会出现任何认证。 | |
− | + | 如果服务端发送了一个不含[[ZH:Protocol#加密请求|加密请求]]的[[ZH:Protocol#登入成功|登入成功]],那么客户端就会知道服务器为离线模式 | |
− | == | + | == 我觉得我啥都没做错,但是… == |
− | === | + | === …我的玩家没有生成! === |
− | + | 发送一些常规的数据包之后([[ZH:Protocol#Handshake|Handshake]]、[[ZH:Protocol#开始登入|开始登入]]、[[ZH:Protocol#窗口物品|物品栏]]、[[ZH:Protocol#生成位置|指南针]]和[[ZH:Protocol|区块数据|区块]]),你最后会需要将玩家的[[ZH:Protocol#玩家位置和外观|初始位置]]发送给他们,这样他们就会离开“加载地图中”的屏幕。 | |
− | '' | + | ''注意如果使用了以下步骤,那么一个Minecraft客户端会生成玩家:'' |
− | # | + | # 执行握手(见[[ZH:Protocol Encryption]]) |
− | # | + | # 发送[[ZH:Protocol#生成位置|生成位置]]数据包 |
− | # | + | # 发送[[ZH:Protocol#玩家位置和外观|玩家位置和外观]]数据包 |
− | + | 上述步骤对于Minecraft 1.4.5来说已经足够了,发送数据包是一种很好的形式,因为这会在允许玩家生成之前告知客户端玩家周围的世界 | |
− | === | + | === …我的数据包没有接受到完整的地图区块! === |
− | '' | + | ''主条目:[[ZH:How to Write a Client|如何编写客户端]]'' |
− | + | 标准Minecraft服务端只会在你的客户端发送玩家状态更新数据包时发送完整的区块(任何通过[[ZH:Protocol#玩家位置和外观|玩家位置和外观(0x06)]]的[[ZH:Protocol#玩家|玩家(0x03)]])。 | |
− | === | + | === …所有连接的客户端都无法控制地鬼畜了起来 === |
− | + | 对于较新的客户端来说,你的服务端需要提前发送49个区块而不只是一个。在生成连接客户端''之前''发送7×7的方形区块,中心为他们的位置。 | |
− | === | + | === …客户端试图发送0xFE01开头的无效数据包 === |
− | + | 客户端尝试[[ZH:Server_List_Ping#1.6|合法ping]],这只会在你的服务端没有合适地响应[[ZH:Server List Ping|服务端列表Ping]],包括发送了格式不正确的JSON。 | |
− | === | + | === …“超时”错误不久后客户端失去了连接 === |
− | + | 服务端理应每秒发送一个[[ZH:Protocol#Keep Alive(客户端方)|Keep Alive]]数据包,然后客户端应该使用该数据包的服务端方版本响应。如果任何一方在一段时间内没有接收到Keep Alive,那么它们会断开连接。 | |
− | [[Category:Protocol Details]] | + | [[Category:ZH:Protocol Details]] |
− | [[Category:Minecraft Modern]] | + | [[Category:ZH:Minecraft Modern]] |
− | == | + | == 我应该怎样打开/保存命令方块? == |
− | + | 客户端打开命令方块窗口的过程有一些复杂;客户端实际上使用了[[ZH:Protocol#更新方块实体|更新方块实体(0x09)]]数据包来打开它。 | |
− | + | 首先,客户端必须拥有至少一个为2的{{Minecraft Wiki|zh:Server.properties#op-permission-level|OP权限等级}},否则客户端会拒绝打开命令方块(OP权限等级使用[[ZH:Protocol#实体状态|实体状态]]数据包设置) | |
− | + | 要打开命令方块: | |
− | # '''C'''→'''S''': [[Protocol# | + | # '''C'''→'''S''': [[ZH:Protocol#玩家方块放置|玩家方块放置(0x1C)]],带有位置为右键的命令方块。 |
− | # '''S'''→'''C''': [[Protocol# | + | # '''S'''→'''C''': [[ZH:Protocol#更新方块实体|更新方块实体(0x09)]],带有命令方块的NBT。 |
− | + | 要保存它,使用[[ZH:Plugin channels#MC.7CAutoCmd|<code>MC|AutoCmd</code>插件通道]]。 |
Revision as of 15:10, 17 November 2019
人们总是会有一些关于Minecraft Modern 协议的问题,所以我们将在本文档中讲述其中一些最常见的。如果你仍有麻烦,在IRC上加入我们,irc.freenode.net上的频道#mcdevs.
Contents
协议文档完备了吗?
取决于你的定义,是的!所有的数据包类型都是已知的,而且已经记录了它们的布局。尽管丢失了一些小细节,但是你编写功能性程序所需的一切在这里都有。我们同样收集了预发布版更改的信息,这使得我们快速记载新的发布版。
客户端的正常登入顺序是什么样的?
有关与Mojang服务器的交流,见认证
推荐的登入流程看起来像这样,其中C是客户端而S是服务端:
- 客户端连接至服务端
- C→S: Handshake State=2
- C→S: 开始登入
- S→C: 加密请求
- 客户端认证
- C→S: 加密响应
- 服务端认证,都启用了加密
- S→C: 设置加密(可选的,启用加密)
- S→C: 登入成功
- S→C: 加入游戏
- S→C: 插件消息:带有服务端铭牌的
minecraft:brand
(可选的) - S→C: 服务端难度(可选的)
- S→C: 玩家能力(可选的)
- C→S: 插件消息:带有客户端铭牌的
minecraft:brand
(可选的) - C→S: 客户端设置
- S→C: 手持物品改变
- S→C: 声明配方
- S→C: 标签
- S→C: 实体状态
- S→C: 声明命令
- S→C: 解锁配方
- S→C: 玩家位置和外观
- S→C: 玩家信息(添加玩家动作)
- S→C: 玩家信息(更新延迟动作)
- S→C: 更新视图位置
- S→C: 更新光照(以玩家位置为中心的方形,每个区块发送一个)
- S→C: 区块数据(以玩家位置为中心的方形,每个区块发送一个)
- S→C: 世界边界(一旦世界结束加载)
- S→C: 生成位置(“家”生成,不是登入时客户端生成的位置)
- S→C: 玩家位置和外观(必需的,告诉客户端已准备好生成)
- C→S: 传送确认
- C→S: 玩家位置和外观(来确认生成位置)
- C→S: 客户端状态(在接受区块之前或之时发送,还需进一步测试,如果没有发送服务端也可正确处理)
- S→C: 物品栏、实体等等
离线模式
如果服务端为离线模式,它不会发送加密请求数据包,相似地,客户端也不应发送加密响应。在这种情况下,从不会启用加密,也不会出现任何认证。
如果服务端发送了一个不含加密请求的登入成功,那么客户端就会知道服务器为离线模式
我觉得我啥都没做错,但是…
…我的玩家没有生成!
发送一些常规的数据包之后(Handshake、开始登入、物品栏、指南针和区块数据|区块),你最后会需要将玩家的初始位置发送给他们,这样他们就会离开“加载地图中”的屏幕。
注意如果使用了以下步骤,那么一个Minecraft客户端会生成玩家:
- 执行握手(见ZH:Protocol Encryption)
- 发送生成位置数据包
- 发送玩家位置和外观数据包
上述步骤对于Minecraft 1.4.5来说已经足够了,发送数据包是一种很好的形式,因为这会在允许玩家生成之前告知客户端玩家周围的世界
…我的数据包没有接受到完整的地图区块!
主条目:如何编写客户端
标准Minecraft服务端只会在你的客户端发送玩家状态更新数据包时发送完整的区块(任何通过玩家位置和外观(0x06)的玩家(0x03))。
…所有连接的客户端都无法控制地鬼畜了起来
对于较新的客户端来说,你的服务端需要提前发送49个区块而不只是一个。在生成连接客户端之前发送7×7的方形区块,中心为他们的位置。
…客户端试图发送0xFE01开头的无效数据包
客户端尝试合法ping,这只会在你的服务端没有合适地响应服务端列表Ping,包括发送了格式不正确的JSON。
…“超时”错误不久后客户端失去了连接
服务端理应每秒发送一个Keep Alive数据包,然后客户端应该使用该数据包的服务端方版本响应。如果任何一方在一段时间内没有接收到Keep Alive,那么它们会断开连接。
我应该怎样打开/保存命令方块?
客户端打开命令方块窗口的过程有一些复杂;客户端实际上使用了更新方块实体(0x09)数据包来打开它。
首先,客户端必须拥有至少一个为2的OP权限等级,否则客户端会拒绝打开命令方块(OP权限等级使用实体状态数据包设置)
要打开命令方块:
- C→S: 玩家方块放置(0x1C),带有位置为右键的命令方块。
- S→C: 更新方块实体(0x09),带有命令方块的NBT。
要保存它,使用MC|AutoCmd
插件通道。