パケット送受信と構造
Bedrock Edition における通信はすべて、バイナリエンコードされたパケットを通じて行われます。gophertunnel では、minecraft/protocol/packet パッケージ内に Bedrock プロトコルの全パケットが Go の構造体として厳密に型定義されています。
パケットのインターフェース
すべてのパケットは packet.Packet インターフェースを実装しています。
go
type Packet interface {
// パケットの一意なID (packet.IDText など)
ID() uint32
// protocol.IO (ReaderまたはWriter) を使ったシリアライズ / デシリアライズ
Marshal(io protocol.IO)
}1つのメソッドで双方向処理
Go では Encode / Decode を分けることが多いですが、gophertunnel では protocol.IO という読み書き両対応のインターフェースを使用し、1つの Marshal メソッドで両方の処理を記述する設計になっています。
パケットの読み込み (ReadPacket)
conn.ReadPacket() は、受信した生パケットを packet.Pool に基づいて自動デコードし、具象型のポインタを返します。
go
for {
pk, err := conn.ReadPacket()
if err != nil {
log.Printf("接続終了: %v", err)
break
}
// 型アサーションや型スイッチで処理を分岐
switch p := pk.(type) {
case *packet.Text:
fmt.Printf("[%s] %s\n", p.SourceName, p.Message)
case *packet.MovePlayer:
fmt.Printf("プレイヤー移動: %v, Yaw: %.2f, Pitch: %.2f\n",
p.Position, p.Yaw, p.Pitch)
case *packet.LevelChunk:
fmt.Printf("チャンク受信: X=%d, Z=%d, サブチャンク数=%d\n",
p.Position.X(), p.Position.Z(), p.SubChunkCount)
case *packet.Disconnect:
fmt.Printf("キック/切断されました: %s\n", p.Message)
return
}
}並行呼び出しの禁止
minecraft.Conn の ReadPacket() は単一の goroutine からのみ呼び出す必要があります(同時に複数の goroutine から呼ぶことは禁止されています)。一方、WritePacket() は複数の goroutine から同時に呼び出しても安全です。
パケットの送信 (WritePacket)
パケットを送信したいときは、対象のパケット構造体をインスタンス化して conn.WritePacket(pk) を呼び出します。
例: チャットメッセージの送信
go
// サーバーへチャットを送信 (クライアント側)
err := conn.WritePacket(&packet.Text{
TextType: packet.TextTypeChat,
NeedsTranslation: false,
SourceName: conn.IdentityData().DisplayName,
Message: "こんにちは!gophertunnelから接続しています",
})例: コマンドの実行
go
// サーバーへコマンドリクエストを送信
err := conn.WritePacket(&packet.CommandRequest{
CommandLine: "/time set day",
CommandOrigin: protocol.CommandOrigin{
Origin: protocol.CommandOriginPlayer,
UUID: uuid.MustParse(conn.IdentityData().Identity),
},
Internal: false,
})例: プレイヤーの移動
go
// 自身の位置をサーバーに報告
err := conn.WritePacket(&packet.MovePlayer{
EntityRuntimeID: conn.GameData().EntityRuntimeID,
Position: mgl32.Vec3{100, 64, 200},
Pitch: 0,
Yaw: 90,
HeadYaw: 90,
Mode: packet.MoveModeNormal,
OnGround: true,
})代表的なパケット一覧
| パケット名 | 定数 ID | 用途・送受信方向 |
|---|---|---|
packet.Text | IDText | チャット、トースト、システム通知(双方向) |
packet.MovePlayer | IDMovePlayer | プレイヤーの位置・向き・接地状態(双方向) |
packet.LevelChunk | IDLevelChunk | チャンクブロックデータ・バイオームデータ(Server -> Client) |
packet.InventoryTransaction | IDInventoryTransaction | アイテム使用、インベントリ移動、ブロック配置(Client -> Server) |
packet.PlayerAction | IDPlayerAction | スニーク、ジャンプ、ブロック採掘開始/中止(Client -> Server) |
packet.CommandRequest | IDCommandRequest | / コマンドの実行要求(Client -> Server) |
packet.Disconnect | IDDisconnect | 理由付き切断メッセージ(Server -> Client) |