Difference between revisions of "Zh:Protocol FAQ"

From wiki.vg
Jump to navigation Jump to search
m (Kaniol moved page ZH:协议FAQ to ZH:Protocol FAQ)
Line 1: Line 1:
People very, very often have questions regarding the Minecraft Modern [[Protocol]], so we'll try to address some of the most common ones on this document. If you're still having trouble, join us on IRC, channel [irc://irc.freenode.net/mcdevs #mcdevs on irc.freenode.net].
+
人们总是会有一些关于Minecraft Modern [[ZH:Protocol|协议]]的问题,所以我们将在本文档中讲述其中一些最常见的。如果你仍有麻烦,在IRC上加入我们,[irc://irc.freenode.net/mcdevs irc.freenode.net上的频道#mcdevs].
  
== Is the protocol documentation complete? ==
+
== 协议文档完备了吗? ==
  
Depending on your definition, ''yes''! All packet types are known and their layout documented. Some finer details are missing, but everything you need to make functional programs is present. We also collect information on the [[pre-release protocol]] changes, allowing us to quickly document new releases.
+
取决于你的定义,''是的''!所有的数据包类型都是已知的,而且已经记录了它们的布局。尽管丢失了一些小细节,但是你编写功能性程序所需的一切在这里都有。我们同样收集了[[ZH:pre-release protocol|预发布版]]更改的信息,这使得我们快速记载新的发布版。
  
== What's the normal login sequence for a client? ==
+
== 客户端的正常登入顺序是什么样的? ==
  
See [[Authentication]] for communication with Mojang's servers.
+
有关与Mojang服务器的交流,见[[ZH:Authentication|认证]]
  
The recommended login sequence looks like this, where '''C''' is the client and '''S''' is the server:
+
推荐的登入流程看起来像这样,其中'''C'''是客户端而'''S'''是服务端:
  
# Client connects to server
+
# 客户端连接至服务端
# '''C→S''': [[Protocol#Handshake|Handshake]] State=2
+
# '''C'''→'''S''': [[ZH:Protocol#Handshake|Handshake]] State=2
# '''C→S''': [[Protocol#Login Start|Login Start]]
+
# '''C'''→'''S''': [[ZH:Protocol#开始登入|开始登入]]
# '''S→C''': [[Protocol#Encryption Request|Encryption Request]]
+
# '''S'''→'''C''': [[ZH:Protocol#加密请求|加密请求]]
# Client auth
+
# 客户端认证
# '''C→S''': [[Protocol#Encryption Response|Encryption Response]]
+
# '''C'''→'''S''': [[ZH:Protocol#加密响应|加密响应]]
# Server auth, both enable encryption
+
# 服务端认证,都启用了加密
# '''S→C''': [[Protocol#Set Compression|Set Compression]] (Optional, enables compression)
+
# '''S'''→'''C''': [[ZH:Protocol#设置加密|设置加密]](可选的,启用加密)
# '''S→C''': [[Protocol#Login Success|Login Success]]
+
# '''S'''→'''C''': [[ZH:Protocol#登入成功|登入成功]]
# '''S→C''': [[Protocol#Join Game|Join Game]]
+
# '''S'''→'''C''': [[ZH:Protocol#加入游戏|加入游戏]]
# '''S→C''': [[Protocol#Plugin Message (clientbound) |Plugin Message]]: [[Plugin channel#minecraft%3Abrand|<code>minecraft:brand</code>]] with the server's brand (Optional)
+
# '''S'''→'''C''': [[ZH:Protocol#插件消息(客户端方)|插件消息]]:带有服务端铭牌的[[ZH:Plugin channel#minecraft%3Abrand|<code>minecraft:brand</code>]](可选的)
# '''S→C''': [[Protocol#Server Difficulty|Server Difficulty]] (Optional)
+
# '''S'''→'''C''': [[ZH:Protocol#服务端难度|服务端难度]](可选的)
# '''S→C''': [[Protocol#Player Abilities (clientbound)|Player Abilities]] (Optional)
+
# '''S'''→'''C''': [[ZH:Protocol#玩家能力(客户端方)|玩家能力]](可选的)
# '''C→S''': [[Protocol#Plugin Message (serverbound)|Plugin Message]]: [[Plugin channel#minecraft%3Abrand|<code>minecraft:brand</code>]] with the client's brand (Optional)
+
# '''C'''→'''S''': [[ZH:Protocol#插件消息(服务端方)|插件消息]]:带有客户端铭牌的[[ZH:Plugin channel#minecraft%3Abrand|<code>minecraft:brand</code>]](可选的)
# '''C→S''': [[Protocol#Client Settings|Client Settings]]
+
# '''C'''→'''S''': [[ZH:Protocol#客户端设置|客户端设置]]
# '''S→C''': [[Protocol#Held Item Change (clientbound)|Held Item Change]]
+
# '''S'''→'''C''': [[ZH:Protocol#手持物品改变(客户端方)|手持物品改变]]
# '''S→C''': [[Protocol#Declare Recipes|Declare Recipes]]
+
# '''S'''→'''C''': [[ZH:Protocol#声明配方|声明配方]]
# '''S→C''': [[Protocol#Tags|Tags]]
+
# '''S'''→'''C''': [[ZH:Protocol#标签|标签]]
# '''S→C''': [[Protocol#Entity Status|Entity Status]]
+
# '''S'''→'''C''': [[ZH:Protocol#实体状态|实体状态]]
# '''S→C''': [[Protocol#Declare Commands|Declare Commands]]
+
# '''S'''→'''C''': [[ZH:Protocol#声明命令|声明命令]]
# '''S→C''': [[Protocol#Unlock Recipes|Unlock Recipes]]
+
# '''S'''→'''C''': [[ZH:Protocol#解锁配方|解锁配方]]
# '''S→C''': [[Protocol#Player Position And Look (clientbound)|Player Position And Look]]
+
# '''S'''→'''C''': [[ZH:Protocol#玩家位置和外观(客户端方)|玩家位置和外观]]
# '''S→C''': [[Protocol#Player Info|Player Info]] (Add Player action)
+
# '''S'''→'''C''': [[ZH:Protocol#玩家信息|玩家信息]](添加玩家动作)
# '''S→C''': [[Protocol#Player Info|Player Info]] (Update latency action)
+
# '''S'''→'''C''': [[ZH:Protocol#玩家信息|玩家信息]](更新延迟动作)
# '''S→C''': [[Protocol#Update View Position|Update View Position]]
+
# '''S'''→'''C''': [[ZH:Protocol#更新视图位置|更新视图位置]]
# '''S→C''': [[Protocol#Update Light|Update Light]] (One sent for each chunk in a square centered on the player's position)
+
# '''S'''→'''C''': [[ZH:Protocol#更新光照|更新光照]](以玩家位置为中心的方形,每个区块发送一个)
# '''S→C''': [[Protocol#Chunk Data|Chunk Data]] (One sent for each chunk in a square centered on the player's position)
+
# '''S'''→'''C''': [[ZH:Protocol#区块数据|区块数据]](以玩家位置为中心的方形,每个区块发送一个)
# '''S→C''': [[Protocol#World Border|World Border]] (Once the world is finished loading)
+
# '''S'''→'''C''': [[ZH:Protocol#世界边界|世界边界]](一旦世界结束加载)
# '''S→C''': [[Protocol#Spawn Position|Spawn Position]] (“home” spawn, not where the client will spawn on login)
+
# '''S'''→'''C''': [[ZH:Protocol#生成位置|生成位置]](“家”生成,不是登入时客户端生成的位置)
# '''S→C''': [[Protocol#Player Position And Look (clientbound)|Player Position And Look]] (Required, tells the client they're ready to spawn)
+
# '''S'''→'''C''': [[ZH:Protocol#玩家位置和外观(客户端方)|玩家位置和外观]](必需的,告诉客户端已准备好生成)
# '''C→S''': [[Protocol#Teleport Confirm|Teleport Confirm]]
+
# '''C'''→'''S''': [[ZH:Protocol#传送确认|传送确认]]
# '''C→S''': [[Protocol#Player Position And Look (serverbound)|Player Position And Look]] (to confirm the spawn position)
+
# '''C'''→'''S''': [[ZH:Protocol#玩家位置和外观(服务端方)|玩家位置和外观]](来确认生成位置)
# '''C→S''': [[Protocol#Client Status|Client Status]] (sent either before or while receiving chunks, further testing needed, server handles correctly if not sent)
+
# '''C'''→'''S''': [[ZH:Protocol#客户端状态|客户端状态]](在接受区块之前或之时发送,还需进一步测试,如果没有发送服务端也可正确处理)
# '''S→C''': inventory, entities, etc
+
# '''S'''→'''C''': 物品栏、实体等等
  
== Offline mode ==
+
== 离线模式 ==
If the server is in offline mode, it will not send the [[Protocol#Encryption Request|Encryption Request]] packet, and likewise, the client should not send [[Protocol#Encryption Response|Encryption Response]]. In this case, encryption is never enabled, and no authentication is performed.
+
如果服务端为离线模式,它不会发送[[ZH:Protocol#加密请求|加密请求]]数据包,相似地,客户端也不应发送[[ZH:Protocol#加密响应|加密响应]]。在这种情况下,从不会启用加密,也不会出现任何认证。
  
Clients can tell that a server is in offline mode if the server sends a [[Protocol#Login Success|Logic Success]] without sending [[Protocol#Encryption Request|Encryption Request]].
+
如果服务端发送了一个不含[[ZH:Protocol#加密请求|加密请求]][[ZH:Protocol#登入成功|登入成功]],那么客户端就会知道服务器为离线模式
  
== I think I've done everything right, but… ==
+
== 我觉得我啥都没做错,但是… ==
  
=== …my player isn't spawning! ===
+
=== …我的玩家没有生成! ===
  
After sending the common-sense packets ([[Protocol#Handshake|Handshake]], [[Protocol#Login Start|Login Start]], [[Protocol#Window Items|inventory]], [[Protocol#Spawn Position|compass]], and [[Protocol#Chunk Data|chunks]]), you need to finally send the player their [[Protocol#Player Position And Look|initial position]] for them to leave the “Loading Map” screen.
+
发送一些常规的数据包之后([[ZH:Protocol#Handshake|Handshake]][[ZH:Protocol#开始登入|开始登入]][[ZH:Protocol#窗口物品|物品栏]][[ZH:Protocol#生成位置|指南针]][[ZH:Protocol|区块数据|区块]]),你最后会需要将玩家的[[ZH:Protocol#玩家位置和外观|初始位置]]发送给他们,这样他们就会离开“加载地图中”的屏幕。
  
''Note that if the following steps are taken, a Minecraft client will spawn the player:''
+
''注意如果使用了以下步骤,那么一个Minecraft客户端会生成玩家:''
  
# Do Handshake (see [[Protocol Encryption]])
+
# 执行握手(见[[ZH:Protocol Encryption]])
# Send [[Protocol#Spawn Position|Spawn Position]] packet
+
# 发送[[ZH:Protocol#生成位置|生成位置]]数据包
# Send [[Protocol#Player Position And Look|Player Position And Look]] packet
+
# 发送[[ZH:Protocol#玩家位置和外观|玩家位置和外观]]数据包
  
While the above steps are sufficient for Minecraft 1.4.5, it is good form to send packets that inform the client about the world around the player before allowing the player to spawn.
+
上述步骤对于Minecraft 1.4.5来说已经足够了,发送数据包是一种很好的形式,因为这会在允许玩家生成之前告知客户端玩家周围的世界
  
=== …my client isn't receiving complete map chunks! ===
+
=== …我的数据包没有接受到完整的地图区块! ===
''Main article: [[How to Write a Client]]''
+
''主条目:[[ZH:How to Write a Client|如何编写客户端]]''
  
The standard Minecraft server sends full chunks only when your client is sending player status update packets (any of [[Protocol#Player|Player (0x03)]] through [[Protocol#Player Position And Look|Player Position And Look (0x06)]]).
+
标准Minecraft服务端只会在你的客户端发送玩家状态更新数据包时发送完整的区块(任何通过[[ZH:Protocol#玩家位置和外观|玩家位置和外观(0x06)]][[ZH:Protocol#玩家|玩家(0x03)]])。
  
=== …all connecting clients spasm and jerk uncontrollably! ===
+
=== …所有连接的客户端都无法控制地鬼畜了起来 ===
  
For newer clients, your server needs to send 49 chunks ahead of time, not just one. Send a 7×7 square of chunks, centered on the connecting client's position, ''before'' spawning them.
+
对于较新的客户端来说,你的服务端需要提前发送49个区块而不只是一个。在生成连接客户端''之前''发送7×7的方形区块,中心为他们的位置。
  
=== …the client is trying to send an invalid packet that begins with 0xFE01 ===
+
=== …客户端试图发送0xFE01开头的无效数据包 ===
  
The client is attempting a [[Server_List_Ping#1.6|legacy ping]], this happens if your server did not respond to the [[Server List Ping]] properly, including if it sent malformed JSON.
+
客户端尝试[[ZH:Server_List_Ping#1.6|合法ping]],这只会在你的服务端没有合适地响应[[ZH:Server List Ping|服务端列表Ping]],包括发送了格式不正确的JSON。
  
=== ...the client disconnects after some time with a "Timed out" error ===
+
=== …“超时”错误不久后客户端失去了连接 ===
  
The server is expected to send a [[Protocol#Keep Alive (clientbound)|Keep Alive]] packet every second, and the client should respond with the serverbound version of that packet. If either party does not receive keep alives for some period of time, they will disconnect.
+
服务端理应每秒发送一个[[ZH:Protocol#Keep Alive(客户端方)|Keep Alive]]数据包,然后客户端应该使用该数据包的服务端方版本响应。如果任何一方在一段时间内没有接收到Keep Alive,那么它们会断开连接。
  
[[Category:Protocol Details]]
+
[[Category:ZH:Protocol Details]]
[[Category:Minecraft Modern]]
+
[[Category:ZH:Minecraft Modern]]
  
== How do I open/save a command block? ==
+
== 我应该怎样打开/保存命令方块? ==
  
The process to actually open the command block window clientside is somewhat complex; the client actually uses the [[Protocol#Update Block Entity|Update Block Entity (0x09)]] packet to open it.
+
客户端打开命令方块窗口的过程有一些复杂;客户端实际上使用了[[ZH:Protocol#更新方块实体|更新方块实体(0x09)]]数据包来打开它。
  
First, the client must have at least an {{Minecraft Wiki|Server.properties#op-permission-level|OP permission level}} of 2, or else the client will refuse to open the command block.  (The op permission level is set with the [[Protocol#Entity Status|Entity Status]] packet)
+
首先,客户端必须拥有至少一个为2的{{Minecraft Wiki|zh:Server.properties#op-permission-level|OP权限等级}},否则客户端会拒绝打开命令方块(OP权限等级使用[[ZH:Protocol#实体状态|实体状态]]数据包设置)
  
To actually open the command block:
+
要打开命令方块:
  
# '''C'''→'''S''': [[Protocol#Player Block Placement|Player Block Placement (0x1C)]], with the position being the command block that was right-clicked.
+
# '''C'''→'''S''': [[ZH:Protocol#玩家方块放置|玩家方块放置(0x1C)]],带有位置为右键的命令方块。
# '''S'''→'''C''': [[Protocol#Update Block Entity|Update Block Entity (0x09)]], with the NBT of the command block.
+
# '''S'''→'''C''': [[ZH:Protocol#更新方块实体|更新方块实体(0x09)]],带有命令方块的NBT。
  
And to save it, use the [[Plugin channels#MC.7CAutoCmd|<code>MC|AutoCmd</code> plugin channel]].
+
要保存它,使用[[ZH:Plugin channels#MC.7CAutoCmd|<code>MC|AutoCmd</code>插件通道]]

Revision as of 15:10, 17 November 2019

人们总是会有一些关于Minecraft Modern 协议的问题,所以我们将在本文档中讲述其中一些最常见的。如果你仍有麻烦,在IRC上加入我们,irc.freenode.net上的频道#mcdevs.

协议文档完备了吗?

取决于你的定义,是的!所有的数据包类型都是已知的,而且已经记录了它们的布局。尽管丢失了一些小细节,但是你编写功能性程序所需的一切在这里都有。我们同样收集了预发布版更改的信息,这使得我们快速记载新的发布版。

客户端的正常登入顺序是什么样的?

有关与Mojang服务器的交流,见认证

推荐的登入流程看起来像这样,其中C是客户端而S是服务端:

  1. 客户端连接至服务端
  2. CS: Handshake State=2
  3. CS: 开始登入
  4. SC: 加密请求
  5. 客户端认证
  6. CS: 加密响应
  7. 服务端认证,都启用了加密
  8. SC: 设置加密(可选的,启用加密)
  9. SC: 登入成功
  10. SC: 加入游戏
  11. SC: 插件消息:带有服务端铭牌的minecraft:brand(可选的)
  12. SC: 服务端难度(可选的)
  13. SC: 玩家能力(可选的)
  14. CS: 插件消息:带有客户端铭牌的minecraft:brand(可选的)
  15. CS: 客户端设置
  16. SC: 手持物品改变
  17. SC: 声明配方
  18. SC: 标签
  19. SC: 实体状态
  20. SC: 声明命令
  21. SC: 解锁配方
  22. SC: 玩家位置和外观
  23. SC: 玩家信息(添加玩家动作)
  24. SC: 玩家信息(更新延迟动作)
  25. SC: 更新视图位置
  26. SC: 更新光照(以玩家位置为中心的方形,每个区块发送一个)
  27. SC: 区块数据(以玩家位置为中心的方形,每个区块发送一个)
  28. SC: 世界边界(一旦世界结束加载)
  29. SC: 生成位置(“家”生成,不是登入时客户端生成的位置)
  30. SC: 玩家位置和外观(必需的,告诉客户端已准备好生成)
  31. CS: 传送确认
  32. CS: 玩家位置和外观(来确认生成位置)
  33. CS: 客户端状态(在接受区块之前或之时发送,还需进一步测试,如果没有发送服务端也可正确处理)
  34. SC: 物品栏、实体等等

离线模式

如果服务端为离线模式,它不会发送加密请求数据包,相似地,客户端也不应发送加密响应。在这种情况下,从不会启用加密,也不会出现任何认证。

如果服务端发送了一个不含加密请求登入成功,那么客户端就会知道服务器为离线模式

我觉得我啥都没做错,但是…

…我的玩家没有生成!

发送一些常规的数据包之后(Handshake开始登入物品栏指南针区块数据|区块),你最后会需要将玩家的初始位置发送给他们,这样他们就会离开“加载地图中”的屏幕。

注意如果使用了以下步骤,那么一个Minecraft客户端会生成玩家:

  1. 执行握手(见ZH:Protocol Encryption)
  2. 发送生成位置数据包
  3. 发送玩家位置和外观数据包

上述步骤对于Minecraft 1.4.5来说已经足够了,发送数据包是一种很好的形式,因为这会在允许玩家生成之前告知客户端玩家周围的世界

…我的数据包没有接受到完整的地图区块!

主条目:如何编写客户端

标准Minecraft服务端只会在你的客户端发送玩家状态更新数据包时发送完整的区块(任何通过玩家位置和外观(0x06)玩家(0x03))。

…所有连接的客户端都无法控制地鬼畜了起来

对于较新的客户端来说,你的服务端需要提前发送49个区块而不只是一个。在生成连接客户端之前发送7×7的方形区块,中心为他们的位置。

…客户端试图发送0xFE01开头的无效数据包

客户端尝试合法ping,这只会在你的服务端没有合适地响应服务端列表Ping,包括发送了格式不正确的JSON。

…“超时”错误不久后客户端失去了连接

服务端理应每秒发送一个Keep Alive数据包,然后客户端应该使用该数据包的服务端方版本响应。如果任何一方在一段时间内没有接收到Keep Alive,那么它们会断开连接。

我应该怎样打开/保存命令方块?

客户端打开命令方块窗口的过程有一些复杂;客户端实际上使用了更新方块实体(0x09)数据包来打开它。

首先,客户端必须拥有至少一个为2的OP权限等级,否则客户端会拒绝打开命令方块(OP权限等级使用实体状态数据包设置)

要打开命令方块:

  1. CS: 玩家方块放置(0x1C),带有位置为右键的命令方块。
  2. SC: 更新方块实体(0x09),带有命令方块的NBT。

要保存它,使用MC|AutoCmd插件通道