aboutsummaryrefslogtreecommitdiffstats
path: root/packet/command/packetentity/packetentity.go
blob: 6accec719e60b3440e8d1085454c7d53da9dc598 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package packetentity

import (
	"github.com/osm/quake/common/buffer"
	"github.com/osm/quake/common/context"
	"github.com/osm/quake/packet/command/packetentitydelta"
	"github.com/osm/quake/protocol"
	"github.com/osm/quake/protocol/fte"
)

type Command struct {
	FTEProtocolExtension uint32

	Bits              uint16
	MoreBits          byte
	EvenMoreBits      byte
	PacketEntityDelta *packetentitydelta.Command
}

func (cmd *Command) Bytes() []byte {
	buf := buffer.New()

	buf.PutUint16(cmd.Bits)

	if cmd.Bits == 0 {
		goto end
	}

	if cmd.Bits&protocol.URemove != 0 {
		if cmd.Bits&protocol.UMoreBits != 0 &&
			cmd.FTEProtocolExtension&fte.ExtensionEntityDbl != 0 {
			buf.PutByte(cmd.MoreBits)

			if cmd.MoreBits&fte.UEvenMore != 0 {
				buf.PutByte(cmd.EvenMoreBits)
			}
		}
		goto end
	}

	if cmd.PacketEntityDelta != nil {
		buf.PutBytes(cmd.PacketEntityDelta.Bytes())
	}

end:
	return buf.Bytes()
}

func Parse(ctx *context.Context, buf *buffer.Buffer) ([]*Command, error) {
	var err error
	var cmds []*Command

	for {
		var cmd Command
		cmd.FTEProtocolExtension = ctx.GetFTEProtocolExtension()

		if cmd.Bits, err = buf.GetUint16(); err != nil {
			return nil, err
		}

		if cmd.Bits == 0 {
			break
		}

		if cmd.Bits&protocol.URemove != 0 {
			if cmd.Bits&protocol.UMoreBits != 0 &&
				cmd.FTEProtocolExtension&fte.ExtensionEntityDbl != 0 {
				if cmd.MoreBits, err = buf.ReadByte(); err != nil {
					return nil, err
				}

				if cmd.MoreBits&fte.UEvenMore != 0 {
					if cmd.EvenMoreBits, err = buf.ReadByte(); err != nil {
						return nil, err
					}
				}
			}
			goto next
		}

		cmd.PacketEntityDelta, err = packetentitydelta.Parse(ctx, buf, cmd.Bits)
		if err != nil {
			return nil, err
		}
	next:
		cmds = append(cmds, &cmd)
	}

	return cmds, nil
}