Files
Frodding/net/packets/packet.go
2026-03-03 15:05:55 +03:00

196 lines
3.8 KiB
Go

package packets
import (
"bytes"
"encoding/binary"
"math"
)
type IPacket interface {
GetID() byte
Encode()
Decode()
GetBuffer() []byte
SetBuffer([]byte)
}
type Packet struct {
id byte
buf *bytes.Buffer
raw []byte
pos int
}
func NewPacket(id byte) *Packet {
return &Packet{id: id, buf: &bytes.Buffer{}}
}
func (p *Packet) GetID() byte { return p.id }
func (p *Packet) GetBuffer() []byte { return p.buf.Bytes() }
func (p *Packet) SetBuffer(data []byte) { p.raw = data; p.pos = 0 }
func (p *Packet) PutByte(v byte) { p.buf.WriteByte(v) }
func (p *Packet) PutBytes(v []byte) { p.buf.Write(v) }
func (p *Packet) PutBool(v bool) {
if v {
p.buf.WriteByte(0x01)
} else {
p.buf.WriteByte(0x00)
}
}
func (p *Packet) PutShort(v int16) {
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, uint16(v))
p.buf.Write(b)
}
func (p *Packet) PutLShort(v uint16) {
b := make([]byte, 2)
binary.LittleEndian.PutUint16(b, v)
p.buf.Write(b)
}
func (p *Packet) PutInt(v int32) {
b := make([]byte, 4)
binary.BigEndian.PutUint32(b, uint32(v))
p.buf.Write(b)
}
func (p *Packet) PutLInt(v int32) {
b := make([]byte, 4)
binary.LittleEndian.PutUint32(b, uint32(v))
p.buf.Write(b)
}
func (p *Packet) PutLLong(v int64) {
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, uint64(v))
p.buf.Write(b)
}
func (p *Packet) PutLFloat(v float32) {
b := make([]byte, 4)
binary.LittleEndian.PutUint32(b, math.Float32bits(v))
p.buf.Write(b)
}
func (p *Packet) PutVarInt(v int32) {
p.PutUVarInt((uint32(v) << 1) ^ uint32(v>>31))
}
func (p *Packet) PutUVarInt(v uint32) {
for v >= 0x80 {
p.buf.WriteByte(byte(v&0x7f) | 0x80)
v >>= 7
}
p.buf.WriteByte(byte(v))
}
func (p *Packet) PutVarLong(v int64) {
p.PutUVarLong((uint64(v) << 1) ^ uint64(v>>63))
}
func (p *Packet) PutUVarLong(v uint64) {
for v >= 0x80 {
p.buf.WriteByte(byte(v&0x7f) | 0x80)
v >>= 7
}
p.buf.WriteByte(byte(v))
}
func (p *Packet) PutString(v string) {
p.PutUVarInt(uint32(len(v)))
p.buf.WriteString(v)
}
func (p *Packet) checkRead(n int) bool { return p.pos+n <= len(p.raw) }
func (p *Packet) GetByte() byte {
if !p.checkRead(1) { return 0 }
b := p.raw[p.pos]; p.pos++; return b
}
func (p *Packet) GetBytes(n int) []byte {
if !p.checkRead(n) { return nil }
b := p.raw[p.pos : p.pos+n]; p.pos += n; return b
}
func (p *Packet) GetBool() bool { return p.GetByte() != 0x00 }
func (p *Packet) GetShort() int16 {
b := p.GetBytes(2)
if b == nil { return 0 }
return int16(binary.BigEndian.Uint16(b))
}
func (p *Packet) GetLShort() uint16 {
b := p.GetBytes(2)
if b == nil { return 0 }
return binary.LittleEndian.Uint16(b)
}
func (p *Packet) GetInt() int32 {
b := p.GetBytes(4)
if b == nil { return 0 }
return int32(binary.BigEndian.Uint32(b))
}
func (p *Packet) GetLInt() int32 {
b := p.GetBytes(4)
if b == nil { return 0 }
return int32(binary.LittleEndian.Uint32(b))
}
func (p *Packet) GetLLong() int64 {
b := p.GetBytes(8)
if b == nil { return 0 }
return int64(binary.LittleEndian.Uint64(b))
}
func (p *Packet) GetLFloat() float32 {
b := p.GetBytes(4)
if b == nil { return 0 }
return math.Float32frombits(binary.LittleEndian.Uint32(b))
}
func (p *Packet) GetVarInt() int32 {
uv := p.GetUVarInt()
return int32((uv >> 1) ^ -(uv & 1))
}
func (p *Packet) GetUVarInt() uint32 {
var v uint32
for i := uint(0); i < 35; i += 7 {
b := p.GetByte()
v |= uint32(b&0x7f) << i
if b&0x80 == 0 { break }
}
return v
}
func (p *Packet) GetVarLong() int64 {
uv := p.GetUVarLong()
return int64((uv >> 1) ^ -(uv & 1))
}
func (p *Packet) GetUVarLong() uint64 {
var v uint64
for i := uint(0); i < 70; i += 7 {
b := p.GetByte()
v |= uint64(b&0x7f) << i
if b&0x80 == 0 { break }
}
return v
}
func (p *Packet) GetString() string {
return string(p.GetBytes(int(p.GetUVarInt())))
}
func (p *Packet) Remaining() int {
if p.pos >= len(p.raw) { return 0 }
return len(p.raw) - p.pos
}