LoginSignup
4
1

More than 5 years have passed since last update.

Quake Engine code review : Network (2/4)の和訳をしてみる

Last updated at Posted at 2017-08-14

Quake Engine code review : Network (2/4)

QuakeWorldのネットワークアーキテクチャは当時、画期的な画期的な革新と見なされていました。 すべてのネットワークゲームの後継者は同じアプローチを採用しました。 ここに詳細があります。

この記事は4つのセクションに分かれています

  1. Architecture section
  2. Network section(本記事)
  3. Prediction section
  4. Rendition section

Network stack

Quakeの基本的なコミュニケーションユニットがコマンドです。 コマンドはプレーヤーの位置、方向、健康、損傷などを更新するために使用されます。
TCP / IPには、リアルタイムシミュレーション(フロー制御、信頼性、パケットシーケンシング)には都合が良いが、Quake World Engine(元のQuakeにあった)には使えません。FPSでは、ASAP(as soon as possible)で受信されない情報は再送信する価値がありません。 したがって、UDP / IPが選択され、信頼性とパケットシーケンスを実装するために、ネットワーク抽象化レイヤ "NetChannel"が作成されました。
OSIの観点から、NetChannelはUDPの上に非常にうまく座っています。

image.png

要約すると、エンジンは主にコマンドを扱います。 送信または受信が必要な場合は、タスクをnetchan.cのNetchan_TransmitメソッドとNetchan_Processメソッドに委譲します(これらのメソッドはクライアントとサーバーで同じです)。

NetChannel Header

NetChannelヘッダーの構造は次のとおりです。

Bit offset Bits 0-15 16-31
0 Sequence Sequence
32 ACK Sequence ACK Sequence
64 QPort Commands
94 ... ...

シーケンスは、送信者によって初期化され、パケットが送信されるたびに1ずつインクリメントされるintです。 シーケンスの目的は複数ですが、最も重要なのは、受信者に失われた/重複した/順序付けられていないUDPパケットを認識させる方法を提供することです。 intの最強ビットはシーケンスの一部ではありませんが、ペイロード(コマンド)に信頼できるデータが含まれていることを示すフラグが付いています(詳細は後で説明します)。
ACK Sequenceもintであり、受信した最後のシーケンス番号と等しい。 これにより、NetChannelのもう一方の端で、パケットが失われたかどうかを確認できます。
QPortはNATルータのバグを回避するためにここにあります(このページの末尾にある続きを読んでください)。 この値は、クライアントの起動時に設定される乱数です。
コマンド:ペイロードです

Reliable messages

信頼できないコマンドは、最後の発信シーケンス番号でマークされて送信されたUDPパケットにグループ化されます。彼らが迷子になった場合、送信者にとっては問題になりません。
信頼性の高いコマンドは別々に扱われますが、重要なのは、送信者と受信者の間で肯定応答されない信頼できるUDPパケットが1つしかないことを理解することです。

すべてのゲームループは、新しい信頼できるコマンドが生成された場合、
message_buf配列に追加されます(メッセージ変数を介してパイロットされます)(1)。
信頼できるコマンドのセットは、メッセージからreliable_bufアレイ(2)に移動されます。これは、reliable_bufが空の場合にのみ発生します(空でない場合、これは他のコマンドセットが先に送信され、まだ確認応答されていないことを意味します)。

最終的なUDPデータグラムが作成されます。NetChannelヘッダーが追加されます(3)。十分なスペースがある場合は、reliable_bufのコンテンツと信頼性の低いコマンドが追加されます。

受信側では、UDPメッセージが解析され、入ってくるシーケンス番号は(パケットが信頼できるデータを含むことを示すビットフラグと共に)発信シーケンスACK(4)に転送される。

次のメッセージを受信したとき:
信頼できるビットフラグがtrueに設定されている場合、UDPパケットはそれを受信者に送信します。 NetChannelはreliable_buf(5)をクリーンアップして、新しいコマンドセットを送信する準備ができています。
信頼できるビットフラグがfalseに設定されている場合、UDPはそれを受信者に送信しません。 NetChannelはreliable_bufの内容を再度送信しようとします。 新しいコマンドがmessage_bufに積み重なります。この配列がオーバーフローした場合、クライアントは破棄されます。

image.png

Flow-Control

私が読むことができる限り、サーバ側でのみフロー制御があります。 クライアントは状態更新をできるだけ速く送信します。
サーバ上でアクティブな最初のフロー制御ルールは、データグラムがクライアントから受信された場合にのみデータグラムを送信することです。 制御フローの第2の形態は、クライアントがコンソール内のレートコマンドを介して設定できるパラメータである「choke」である。 これにより、サーバーは更新メッセージをスキップし、クライアントに送信されるデータの量を減らします。

Important commands

コマンドにはバイトに格納されたタイプコードと、それに続くコマンドのペイロードがあります。 おそらく最も重要なのは、ゲームの状態(frame_t)に関する情報を与えるコマンドです。

  1. svc_packetentitiesとsvc_deltapackententities:ロケットトレイル、爆発、パーティクルなどのエンティティを更新する
  2. svc_playerinfo:プレーヤーの位置、最後のコマンドとコマンドの継続時間をmsec単位で更新する

More on the qport

Qportはバグを回避する為にNetChannelヘッダーに追加されたものです。 Qport導入以前は、Quakeサーバーはその組み合わせ(リモートIP、リモートUDPポート)によってクライアントを識別しました。 ほとんどの場合、これはうまくいきましたが、特定のNATルータは、ポート変換(リモートUDPポート)のスキーマを散発的に変更できます。 UDPポートが信頼できない場合、John Carmack氏は彼の計画の1つで、(リモートIP、NetChannelヘッダーのQport)でクライアントを識別することに決めたと説明しました。 これにより、混乱が修正され、サーバはターゲットUDP応答ポートを即座に調整することができました。

Latency calculation

Quakeエンジンは、最後に送信された64個のコマンド(frame_t配列:フレーム内)を送信時刻と共に格納します。これらのコマンドは、転送に使用されたシーケンス番号(outgoing_sequence)を介して直接アクセスできます。

frame = &cl.frames[cls.netchan.outgoing_sequence & UPDATE_MASK];
frame->senttime = realtime;

    //Send packet to server

サーバからの肯定応答に応じて、コマンドが送信された時刻がシーケンスACKを介して取得されます。 レイテンシは次のように計算されます。

//Receive response from server 

frame = &cl.frames[cls.netchan.incoming_acknowledged & UPDATE_MASK];
frame->receivedtime = realtime;
latency = frame->receivedtime - frame->senttime;

Some elegant things

配列インデックスサイクリング

エンジンのネットワーク部分には、最後に受信した64個のUDPデータグラムが格納されます。 配列を循環する素朴なアプローチは、モジュロ演算子を使うことでした。

arrayIndex =(oldArrayIndex + 1)%64;

代わりに、新しい値は、UPDATE_MASKで "AND"バイナリ演算で計算され、UPDATE_MASKは64-1に等しくなります。
(2のべき乗の剰余を処理する場合、ビット単位AND演算を使用することができる。)

arrayIndex =(oldArrayIndex + 1)&UPDATE_MASK;

実際のコードは実際には:

frame_t * newpacket; newpacket =&frames [cls.netchan.incoming_sequence&UPDATE_MASK];
4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1