144 lines
4.2 KiB
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
|
|
} |