1
0

121 lines
2.6 KiB
Go

package packets
import (
"encoding/binary"
"eq2emu/internal/opcodes"
)
type AppHandler struct {
pool *PacketPool
}
func NewAppHandler(pool *PacketPool) *AppHandler {
return &AppHandler{pool: pool}
}
// Create application packet for sending
func (h *AppHandler) CreateAppPacket(opcode opcodes.AppOpcode, data []byte) *AppPacket {
packet := h.pool.GetAppPacket()
packet.Opcode = opcode
packet.Data = make([]byte, len(data))
copy(packet.Data, data)
return packet
}
// Serialize app packet to protocol packet
func (h *AppHandler) SerializeAppPacket(app *AppPacket, sequence uint16) []byte {
size := 3 + len(app.Data) // opcode(1) + seq(2) + opcode(2) + data
if app.Compressed {
size++ // compression flag
}
data := make([]byte, size)
offset := 0
data[offset] = byte(opcodes.OP_Packet)
offset++
binary.LittleEndian.PutUint16(data[offset:], sequence)
offset += 2
if app.Compressed {
data[offset] = 0xFF
offset++
}
binary.LittleEndian.PutUint16(data[offset:], uint16(app.Opcode))
offset += 2
copy(data[offset:], app.Data)
return data
}
// Create combined packet
func (h *AppHandler) SerializeCombinedPacket(apps []*AppPacket, sequence uint16) []byte {
// Calculate total size
totalSize := 3 // opcode + sequence
for _, app := range apps {
subSize := 2 + len(app.Data) // opcode + data
if subSize < 0xFF {
totalSize += 1 + subSize
} else {
totalSize += 3 + subSize
}
}
data := make([]byte, totalSize)
offset := 0
data[offset] = byte(opcodes.OP_Combined)
offset++
binary.LittleEndian.PutUint16(data[offset:], sequence)
offset += 2
for _, app := range apps {
subSize := 2 + len(app.Data)
// Write length
if subSize < 0xFF {
data[offset] = byte(subSize)
offset++
} else {
data[offset] = 0xFF
offset++
binary.LittleEndian.PutUint16(data[offset:], uint16(subSize))
offset += 2
}
// Write opcode
binary.LittleEndian.PutUint16(data[offset:], uint16(app.Opcode))
offset += 2
// Write data
copy(data[offset:], app.Data)
offset += len(app.Data)
}
return data
}
// Common EQ2 packet helpers
func (h *AppHandler) CreateChatPacket(message string, channel uint8) *AppPacket {
writer := NewPacketWriter()
writer.WriteUint8(channel)
writer.WriteEQ2String(message)
return h.CreateAppPacket(opcodes.OP_EqHearChatCmd, writer.Bytes())
}
func (h *AppHandler) CreatePositionUpdatePacket(playerID uint32, x, y, z float32) *AppPacket {
writer := NewPacketWriter()
writer.WriteUint32(playerID)
writer.WriteFloat32(x)
writer.WriteFloat32(y)
writer.WriteFloat32(z)
return h.CreateAppPacket(opcodes.OP_UpdatePositionMsg, writer.Bytes())
}