《最终幻想14》诗人演奏的通信过程

0.引言

本文主要对最终幻想14中诗人演奏系统的服务器-客户端通信机制进行调查和探讨

主要内容将包括以下几方面

1.《最终幻想14》中的演奏通信格式
2.《最终幻想14》中的诗人演奏系统通信机制
3.从机制中得出的结论

如果你没有兴趣看详细的抓包过程,可以直接跳到第三章结论部分

1.《最终幻想14》中的演奏通信格式

客户端->服务器的演奏数据包

1567255698949

上图为客户端->服务器的演奏数据包

笔者解析如下

1567255626657

黄色部分为实际的演奏数据,数据格式3个Byte为一组,每个byte的组成为【Note间隔|Note|分隔符】

数据格式的一些规定如下

  • 分隔符为0xFF

  • Note的范围在0x18-0x3C

  • Note间隔单位为毫秒

  • Note是以标准midi的note为准

    诗人演奏ui中最左面的键被认为是Note 24(C1) 最右面的键被认为是Note 60(C4)

    ※存在特殊的Note 0xFE,含义为停止当前Note的演奏,例如笛子等乐器的停止

  • 每组数据可能会不存在Note间隔或者Note,但是一定会存在分隔符

    例如没有按键时,演奏数据会是0xFA 0xFF,即间隔250ms

    没有Note间隔的情况比较少见,一般发生在内容包的第一组数据上,为【Note|分隔符】

服务器->客户端的演奏数据包

1567252868628

上图为服务器->客户端的演奏数据包

不难看出结构一致,只有Opcode变为0x02A5,SourceID这里是变成了其他玩家的ID

2.《最终幻想14》中的诗人演奏系统通信机制

❎注意:以下内容仅为笔者根据目前现象进行的猜想,不保证为实际游戏程序的逻辑❎

2-1.键盘采集

  • 当玩家在演奏UI的状态下,键盘采集的结果会转换成note并进行发送
  • 键盘采集的速度/间隔与客户端的FPS有关,当60FPS时我们认为键盘按下并保持13.3ms才会被客户端采集到
  • 客户端不仅仅会采集键盘的按下事件(KeyDown),也会采集键盘的抬起事件(KeyUp)

2-2.数据包组成

  • 一般来说每个数据包包含过去500ms内的按键信息(休眠后的第一包除外,关于休眠请参考本章第3节)

  • 没有的按键信息会用没有Note的【Note间隔|分隔符】的数据填充

  • 我们假设现在Q键对应诗人演奏的最左面的键,当你按下Q键200ms后松开时,客户端会将该按键组包如下

    【Note间隔|0x18(Note C1)|0xFF】【0xC8(间隔200ms)|0xFE(停止Note)|0xFF】

    由于后续没有按键,填充空白到500ms,即整包数据为

    【Note间隔|0x18|0xFF】【0xC8|0xFE|0xFF】【0xFA(250ms)|0xFF】【0x32(50ms)|0xFF】

2-3.通信机制

  • 数据包的发送间隔为500ms

  • 当一个按键包发送后,客户端还会持续发送数据包5次,保持2500ms连续,但是包内容没有任何Note

  • 当5次数据包发送完毕仍然没有按键按下/抬起,客户端会进入一种类似休眠的状态

  • 休眠时采集到按键后,会有1-500ms的唤醒时间,然后再回到500ms周期的发送循环中

    即:休眠后的第一包数据中,包含了过去500-1000ms内的按键信息

    如果从发送数据包的时间点倒推,其发送的按键时间是与现实时间一致的

    但是该数据包直接发送到服务器上,因此相当于比500ms周期延迟了0-500ms

    1567260351641

    如上图所示,玩家在0秒时按下第一个按键,第3秒的时候演奏包不再发送,客户端进入休眠状态

    在3.5秒时玩家进行按键,但是由于休眠机制的存在,本应在第4秒发送出的数据包实际在4.2秒左右发送出

    而且如果有其他按键也会在原有的500毫秒循环上向后延迟0.2秒变为4.2秒,4.7秒,5.2秒……

  • 当检测到上一个按键的键盘抬起事件时,也会发送一包数据。与按键按下时一样,这包数据也会使客户端唤醒 ,会重置2500ms的计数器。

    例:玩家在0秒的时候按下按键,3秒后客户端休眠,在第4秒抬起按键,此时客户端会从休眠中唤醒,发送6包数据后再次进入休眠状态

  • 以长笛为代表的管弦乐器,系统会在第4秒自动发送Note停止,因此即便一直按下按键,也无法在休眠后通过抬起按键使客户端唤醒

2-4 隐藏特性

  • 演奏包的最小note间隔为0x64=100ms 等于150BPM下的16分音符(在4.4之前的版本为125ms)

  • 演奏包中的停止Note(0xFE)只会检测最后一个按下按键的抬起事件

    即:如果先按下A键,松开A键,再按下B键,松开B键,会产生4个事件

    而如果先按下A键,再按下B键,松开A键松开B键,只会产生3个事件,松开A键的事件不会被当成数据包发送

  • 由于本地延迟或其他因素,客户端发送的数据包有可能丢包,这种情况下客户端会在约200ms后重新发送一包演奏包。但是该重发不会影响500ms的周期。

3.结论及一些对策

  1. 如果玩家的演奏中间有超过3秒的停顿,那么每次从停顿中恢复时都会产生一个0-500ms的随机延迟(该延迟不会叠加,请自行思考原因)
  2. 如果玩家的停顿小于6秒,那么可以通过保持按键->在3秒处松开按键的方法保持演奏数据包连续

附录

本文使用的抓包工具为FFXIVMonReborn,可以点击这里下载

知识共享许可协议
本文采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇