1
0
game/server/net/packets.go

144 lines
4.2 KiB
Go

package net
import (
"encoding/binary"
"math"
)
// Message type constants
const (
MSG_LOGIN = 0x01
MSG_POSITION = 0x02
MSG_SPAWN = 0x03
MSG_MOVE = 0x04
MSG_UPDATE = 0x05
MSG_PLAYER_JOINED = 0x06
MSG_PLAYER_LEFT = 0x07
MSG_PLAYER_LIST = 0x08
MSG_CHANGE_COLOR = 0x09
MSG_COLOR_CHANGED = 0x0A
)
// Vec3 represents a 3D vector
type Vec3 struct {
X, Y, Z float32
}
// EncodeSpawnPacket creates a spawn packet
func EncodeSpawnPacket(playerID uint32, position Vec3, color string) []byte {
colorBytes := []byte(color)
msg := make([]byte, 18+len(colorBytes))
msg[0] = MSG_SPAWN
binary.LittleEndian.PutUint32(msg[1:5], playerID)
binary.LittleEndian.PutUint32(msg[5:9], math.Float32bits(position.X))
binary.LittleEndian.PutUint32(msg[9:13], math.Float32bits(position.Y))
binary.LittleEndian.PutUint32(msg[13:17], math.Float32bits(position.Z))
msg[17] = uint8(len(colorBytes))
copy(msg[18:], colorBytes)
return msg
}
// EncodeUpdatePacket creates an update packet
func EncodeUpdatePacket(playerID uint32, position Vec3) []byte {
msg := make([]byte, 17)
msg[0] = MSG_UPDATE
binary.LittleEndian.PutUint32(msg[1:5], playerID)
binary.LittleEndian.PutUint32(msg[5:9], math.Float32bits(position.X))
binary.LittleEndian.PutUint32(msg[9:13], math.Float32bits(position.Y))
binary.LittleEndian.PutUint32(msg[13:17], math.Float32bits(position.Z))
return msg
}
// EncodePlayerJoinedPacket creates a player joined packet
func EncodePlayerJoinedPacket(playerID uint32, position Vec3, color string) []byte {
colorBytes := []byte(color)
msg := make([]byte, 18+len(colorBytes))
msg[0] = MSG_PLAYER_JOINED
binary.LittleEndian.PutUint32(msg[1:5], playerID)
binary.LittleEndian.PutUint32(msg[5:9], math.Float32bits(position.X))
binary.LittleEndian.PutUint32(msg[9:13], math.Float32bits(position.Y))
binary.LittleEndian.PutUint32(msg[13:17], math.Float32bits(position.Z))
msg[17] = uint8(len(colorBytes))
copy(msg[18:], colorBytes)
return msg
}
// EncodePlayerLeftPacket creates a player left packet
func EncodePlayerLeftPacket(playerID uint32) []byte {
msg := make([]byte, 5)
msg[0] = MSG_PLAYER_LEFT
binary.LittleEndian.PutUint32(msg[1:5], playerID)
return msg
}
// EncodeColorChangedPacket creates a color changed packet
func EncodeColorChangedPacket(playerID uint32, color string) []byte {
colorBytes := []byte(color)
msg := make([]byte, 6+len(colorBytes))
msg[0] = MSG_COLOR_CHANGED
binary.LittleEndian.PutUint32(msg[1:5], playerID)
msg[5] = uint8(len(colorBytes))
copy(msg[6:], colorBytes)
return msg
}
// EncodePlayerListPacket creates a player list packet
func EncodePlayerListPacket(players []*Player) []byte {
if len(players) == 0 {
return []byte{MSG_PLAYER_LIST, 0}
}
msg := make([]byte, 1024)
msg[0] = MSG_PLAYER_LIST
msg[1] = uint8(len(players))
offset := 2
for _, p := range players {
binary.LittleEndian.PutUint32(msg[offset:], p.ID)
binary.LittleEndian.PutUint32(msg[offset+4:], math.Float32bits(p.Position.X))
binary.LittleEndian.PutUint32(msg[offset+8:], math.Float32bits(p.Position.Y))
binary.LittleEndian.PutUint32(msg[offset+12:], math.Float32bits(p.Position.Z))
colorBytes := []byte(p.Color)
msg[offset+16] = uint8(len(colorBytes))
copy(msg[offset+17:], colorBytes)
offset += 17 + len(colorBytes)
if offset > 1000 {
break // Prevent overflow
}
}
return msg[:offset]
}
// DecodeMovePacket decodes a move packet
func DecodeMovePacket(data []byte) (playerID uint32, delta Vec3, ok bool) {
if len(data) < 17 {
return 0, Vec3{}, false
}
playerID = binary.LittleEndian.Uint32(data[1:5])
delta.X = math.Float32frombits(binary.LittleEndian.Uint32(data[5:9]))
delta.Y = math.Float32frombits(binary.LittleEndian.Uint32(data[9:13]))
delta.Z = math.Float32frombits(binary.LittleEndian.Uint32(data[13:17]))
return playerID, delta, true
}
// DecodeColorChangePacket decodes a color change packet
func DecodeColorChangePacket(data []byte) (playerID uint32, color string, ok bool) {
if len(data) < 6 {
return 0, "", false
}
playerID = binary.LittleEndian.Uint32(data[1:5])
colorLen := data[5]
if len(data) < 6+int(colorLen) {
return 0, "", false
}
color = string(data[6 : 6+colorLen])
return playerID, color, true
}