diff options
Diffstat (limited to '')
| -rw-r--r-- | demo/mvd/cmd.go | 93 | ||||
| -rw-r--r-- | demo/mvd/damagedone.go | 63 | ||||
| -rw-r--r-- | demo/mvd/demoinfo.go | 35 | ||||
| -rw-r--r-- | demo/mvd/hidden.go | 71 | ||||
| -rw-r--r-- | demo/mvd/mutliple.go | 58 | ||||
| -rw-r--r-- | demo/mvd/parse.go | 133 | ||||
| -rw-r--r-- | demo/mvd/parse_test.go | 59 | ||||
| -rw-r--r-- | demo/mvd/read.go | 46 | ||||
| -rw-r--r-- | demo/mvd/set.go | 35 | ||||
| -rw-r--r-- | demo/mvd/testdata/demo1.mvd | bin | 0 -> 5535264 bytes | |||
| -rw-r--r-- | demo/mvd/testdata/demo2.mvd | bin | 0 -> 816709 bytes | |||
| -rw-r--r-- | demo/mvd/testdata/demo3.mvd | bin | 0 -> 4541251 bytes | |||
| -rw-r--r-- | demo/mvd/testdata/demo4.mvd | bin | 0 -> 428923 bytes | |||
| -rw-r--r-- | demo/mvd/unknown.go | 25 | ||||
| -rw-r--r-- | demo/mvd/usercommand.go | 100 | ||||
| -rw-r--r-- | demo/mvd/weapon.go | 71 | ||||
| -rw-r--r-- | demo/mvd/weaponinstruction.go | 57 | ||||
| -rw-r--r-- | demo/mvd/weaponserverside.go | 75 |
18 files changed, 921 insertions, 0 deletions
diff --git a/demo/mvd/cmd.go b/demo/mvd/cmd.go new file mode 100644 index 0000000..d89f492 --- /dev/null +++ b/demo/mvd/cmd.go @@ -0,0 +1,93 @@ +package mvd + +import ( + "github.com/osm/quake/common/buffer" + "github.com/osm/quake/common/context" +) + +type Cmd struct { + Msec byte + UserAngle [3]float32 + Forward uint16 + Side uint16 + Up uint16 + Buttons byte + Impulse byte + Padding [3]byte + Angle [3]float32 +} + +func (cmd *Cmd) Bytes() []byte { + buf := buffer.New() + + buf.PutByte(cmd.Msec) + + for i := 0; i < 3; i++ { + buf.PutFloat32(cmd.UserAngle[i]) + } + + buf.PutUint16(cmd.Forward) + buf.PutUint16(cmd.Side) + buf.PutUint16(cmd.Up) + buf.PutByte(cmd.Buttons) + buf.PutByte(cmd.Impulse) + + for i := 0; i < 3; i++ { + buf.PutByte(cmd.Padding[i]) + } + + for i := 0; i < 3; i++ { + buf.PutFloat32(cmd.Angle[i]) + } + + return buf.Bytes() +} + +func parseCmd(ctx *context.Context, buf *buffer.Buffer) (*Cmd, error) { + var err error + var cmd Cmd + + if cmd.Msec, err = buf.ReadByte(); err != nil { + return nil, err + } + + for i := 0; i < 3; i++ { + if cmd.UserAngle[i], err = buf.GetFloat32(); err != nil { + return nil, err + } + } + + if cmd.Forward, err = buf.GetUint16(); err != nil { + return nil, err + } + + if cmd.Side, err = buf.GetUint16(); err != nil { + return nil, err + } + + if cmd.Up, err = buf.GetUint16(); err != nil { + return nil, err + } + + if cmd.Buttons, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.Impulse, err = buf.ReadByte(); err != nil { + return nil, err + } + + for i := 0; i < 3; i++ { + if cmd.Padding[i], err = buf.ReadByte(); err != nil { + return nil, err + } + } + + for i := 0; i < 3; i++ { + if cmd.Angle[i], err = buf.GetFloat32(); err != nil { + return nil, err + } + } + + return &cmd, nil +} diff --git a/demo/mvd/damagedone.go b/demo/mvd/damagedone.go new file mode 100644 index 0000000..cf9012a --- /dev/null +++ b/demo/mvd/damagedone.go @@ -0,0 +1,63 @@ +package mvd + +import ( + "github.com/osm/quake/common/buffer" + "github.com/osm/quake/common/context" +) + +type DamageDone struct { + size uint32 + + Data []byte + DeathType uint16 + AttackerEnt uint16 + TargetEnt uint16 + Damage uint16 +} + +func (cmd *DamageDone) Bytes() []byte { + if cmd.size != 8 { + return cmd.Data + } + + buf := buffer.New() + buf.PutUint16(cmd.DeathType) + buf.PutUint16(cmd.AttackerEnt) + buf.PutUint16(cmd.TargetEnt) + buf.PutUint16(cmd.Damage) + + return buf.Bytes() +} + +func parseDamageDone(ctx *context.Context, buf *buffer.Buffer, size uint32) (*DamageDone, error) { + var err error + var cmd DamageDone + + cmd.size = size + if cmd.size != 8 { + if cmd.Data, err = buf.GetBytes(int(cmd.size)); err != nil { + return nil, err + } + + goto end + } + + if cmd.DeathType, err = buf.GetUint16(); err != nil { + return nil, err + } + + if cmd.AttackerEnt, err = buf.GetUint16(); err != nil { + return nil, err + } + + if cmd.TargetEnt, err = buf.GetUint16(); err != nil { + return nil, err + } + + if cmd.Damage, err = buf.GetUint16(); err != nil { + return nil, err + } + +end: + return &cmd, nil +} diff --git a/demo/mvd/demoinfo.go b/demo/mvd/demoinfo.go new file mode 100644 index 0000000..c52a645 --- /dev/null +++ b/demo/mvd/demoinfo.go @@ -0,0 +1,35 @@ +package mvd + +import ( + "github.com/osm/quake/common/buffer" + "github.com/osm/quake/common/context" +) + +type DemoInfo struct { + BlockNumber uint16 + Data []byte +} + +func (cmd *DemoInfo) Bytes() []byte { + buf := buffer.New() + + buf.PutUint16(cmd.BlockNumber) + buf.PutBytes(cmd.Data) + + return buf.Bytes() +} + +func parseDemoInfo(ctx *context.Context, buf *buffer.Buffer, size uint32) (*DemoInfo, error) { + var err error + var cmd DemoInfo + + if cmd.BlockNumber, err = buf.GetUint16(); err != nil { + return nil, err + } + + if cmd.Data, err = buf.GetBytes(int(size) - 2); err != nil { + return nil, err + } + + return &cmd, nil +} diff --git a/demo/mvd/hidden.go b/demo/mvd/hidden.go new file mode 100644 index 0000000..f9b5ebf --- /dev/null +++ b/demo/mvd/hidden.go @@ -0,0 +1,71 @@ +package mvd + +import ( + "github.com/osm/quake/common/buffer" + "github.com/osm/quake/common/context" + "github.com/osm/quake/packet/command" + "github.com/osm/quake/protocol" + "github.com/osm/quake/protocol/mvd" +) + +type HiddenCommand struct { + Size uint32 + Type uint16 + Command command.Command +} + +func (cmd *HiddenCommand) Bytes() []byte { + buf := buffer.New() + + buf.PutUint32(cmd.Size) + buf.PutUint16(cmd.Type) + buf.PutBytes(cmd.Command.Bytes()) + + return buf.Bytes() +} + +func parseHiddenCommands(ctx *context.Context, data []byte) ([]*HiddenCommand, error) { + var err error + var cmds []*HiddenCommand + + buf := buffer.New(buffer.WithData(data)) + + for buf.Off() < buf.Len() { + var cmd HiddenCommand + + if cmd.Size, err = buf.GetUint32(); err != nil { + return nil, err + } + + if cmd.Type, err = buf.GetUint16(); err != nil { + return nil, err + } + + var c command.Command + switch protocol.CommandType(cmd.Type) { + case mvd.HiddenUserCommand: + c, err = parseUserCommand(ctx, buf, cmd.Size) + case mvd.HiddenUserCommandWeapon: + c, err = parseWeapon(ctx, buf, cmd.Size) + case mvd.HiddenDemoInfo: + c, err = parseDemoInfo(ctx, buf, cmd.Size) + case mvd.HiddenDamangeDone: + c, err = parseDamageDone(ctx, buf, cmd.Size) + case mvd.HiddenUserCommandWeaponServerSide: + c, err = parseWeaponServerSide(ctx, buf, cmd.Size) + case mvd.HiddenUserCommandWeaponInstruction: + c, err = parseWeaponInstruction(ctx, buf, cmd.Size) + default: + c, err = parseUnknown(ctx, buf, cmd.Size) + } + + if err != nil { + return cmds, err + } + cmd.Command = c + + cmds = append(cmds, &cmd) + } + + return cmds, nil +} diff --git a/demo/mvd/mutliple.go b/demo/mvd/mutliple.go new file mode 100644 index 0000000..6b66d37 --- /dev/null +++ b/demo/mvd/mutliple.go @@ -0,0 +1,58 @@ +package mvd + +import ( + "github.com/osm/quake/common/buffer" + "github.com/osm/quake/common/context" + "github.com/osm/quake/protocol/mvd" +) + +type Multiple struct { + LastTo uint32 + IsHiddenPacket bool + Size uint32 + HiddenCommands []*HiddenCommand +} + +func (cmd *Multiple) Bytes() []byte { + buf := buffer.New() + + buf.PutUint32(cmd.LastTo) + + if cmd.IsHiddenPacket { + buf.PutUint32(cmd.Size) + + for _, c := range cmd.HiddenCommands { + buf.PutBytes(c.Bytes()) + } + } + + return buf.Bytes() +} + +func parseMultiple(ctx *context.Context, buf *buffer.Buffer) (*Multiple, error) { + var err error + var cmd Multiple + + if cmd.LastTo, err = buf.GetUint32(); err != nil { + return nil, err + } + + if cmd.LastTo == 0 && ctx.GetMVDProtocolExtension()&mvd.ExtensionHiddenMessages != 0 { + cmd.IsHiddenPacket = true + + if cmd.Size, err = buf.GetUint32(); err != nil { + return nil, err + } + + bytes, err := buf.GetBytes(int(cmd.Size)) + if err != nil { + return nil, err + } + + if cmd.HiddenCommands, err = parseHiddenCommands(ctx, bytes); err != nil { + return nil, err + } + } + + return &cmd, nil +} diff --git a/demo/mvd/parse.go b/demo/mvd/parse.go new file mode 100644 index 0000000..20ea811 --- /dev/null +++ b/demo/mvd/parse.go @@ -0,0 +1,133 @@ +package mvd + +import ( + "errors" + + "github.com/osm/quake/common/buffer" + "github.com/osm/quake/common/context" + "github.com/osm/quake/protocol" + "github.com/osm/quake/protocol/mvd" +) + +var ErrUnknownType = errors.New("unknown type") + +type Demo struct { + Data []Data +} + +type Data struct { + Target uint32 + Timestamp byte + Command byte + Cmd *Cmd + Read *Read + Set *Set + Multiple *Multiple +} + +func (d *Demo) Bytes() []byte { + buf := buffer.New() + + for i := 0; i < len(d.Data); i++ { + buf.PutBytes(d.Data[i].Bytes()) + } + + return buf.Bytes() +} + +func (d *Data) Bytes() []byte { + buf := buffer.New() + + buf.PutByte(d.Timestamp) + buf.PutByte(d.Command) + + switch d.Command & 0x7 { + case mvd.DemoMultiple: + buf.PutBytes(d.Multiple.Bytes()) + fallthrough + case mvd.DemoStats: + fallthrough + case mvd.DemoSingle: + fallthrough + case mvd.DemoAll: + fallthrough + case protocol.DemoRead: + buf.PutBytes(d.Read.Bytes()) + case protocol.DemoSet: + buf.PutBytes(d.Set.Bytes()) + case protocol.DemoCmd: + buf.PutBytes(d.Cmd.Bytes()) + } + + return buf.Bytes() +} + +func Parse(ctx *context.Context, data []byte) (*Demo, error) { + var err error + var cmd Demo + + buf := buffer.New(buffer.WithData(data)) + ctx.SetIsMVD(true) + + for buf.Off() < buf.Len() { + var data Data + + process: + if data.Timestamp, err = buf.ReadByte(); err != nil { + return nil, err + } + + if data.Command, err = buf.ReadByte(); err != nil { + return nil, err + } + + switch data.Command & 0x7 { + case mvd.DemoMultiple: + if data.Multiple, err = parseMultiple(ctx, buf); err != nil { + return nil, err + } + data.Target = data.Multiple.LastTo + + if data.Multiple.IsHiddenPacket { + cmd.Data = append(cmd.Data, data) + + if buf.Off() == buf.Len() { + goto end + } + + goto process + } + + fallthrough + case mvd.DemoStats: + fallthrough + case mvd.DemoSingle: + // Target determines which client the data is intended + // to reach and can be used in conjunction with the + // updateuserinfo to determine who the client is. + data.Target = uint32(data.Command >> 3) + fallthrough + case mvd.DemoAll: + fallthrough + case protocol.DemoRead: + if data.Read, err = parseRead(ctx, buf); err != nil { + return nil, err + } + case protocol.DemoSet: + if data.Set, err = parseSet(ctx, buf); err != nil { + return nil, err + } + case protocol.DemoCmd: + if data.Cmd, err = parseCmd(ctx, buf); err != nil { + return nil, err + } + default: + return nil, ErrUnknownType + } + + cmd.Data = append(cmd.Data, data) + } + +end: + return &cmd, nil +} diff --git a/demo/mvd/parse_test.go b/demo/mvd/parse_test.go new file mode 100644 index 0000000..53a00a3 --- /dev/null +++ b/demo/mvd/parse_test.go @@ -0,0 +1,59 @@ +package mvd + +import ( + "crypto/sha256" + "fmt" + "io/ioutil" + "testing" + + "github.com/osm/quake/common/context" +) + +type mvdTest struct { + filePath string + checksum string +} + +var mvdTests = []mvdTest{ + { + filePath: "testdata/demo1.mvd", + checksum: "9489430c9513aed5b8e444df1b0d2040acb55de565c1b3e237dce51c8c103c57", + }, + { + filePath: "testdata/demo2.mvd", + checksum: "d40c3864dd3c052a8379e7e589cd045814ec462f6cf4432a2c94ec740843e30d", + }, + { + filePath: "testdata/demo3.mvd", + checksum: "3dd728aa90fdae100ade62d9b93220b7689f6ebdca6c986d3c2b1208b4e1e33c", + }, + { + filePath: "testdata/demo4.mvd", + checksum: "1f7b2c0ad77608f431028c8e68904400fe406150875a51f793f3395bf3784c90", + }, +} + +func TestParse(t *testing.T) { + for _, mt := range mvdTests { + t.Run(mt.filePath, func(t *testing.T) { + data, err := ioutil.ReadFile(mt.filePath) + if err != nil { + t.Errorf("unable to open demo file, %v", err) + } + + demo, err := Parse(context.New(), data) + if err != nil { + t.Errorf("unable to parse demo, %v", err) + } + + h := sha256.New() + h.Write(demo.Bytes()) + checksum := fmt.Sprintf("%x", h.Sum(nil)) + if checksum != mt.checksum { + t.Errorf("sha256 checksums didn't match") + t.Logf("output: %#v", checksum) + t.Logf("expected: %#v", mt.checksum) + } + }) + } +} diff --git a/demo/mvd/read.go b/demo/mvd/read.go new file mode 100644 index 0000000..20dae8a --- /dev/null +++ b/demo/mvd/read.go @@ -0,0 +1,46 @@ +package mvd + +import ( + "github.com/osm/quake/common/buffer" + "github.com/osm/quake/common/context" + "github.com/osm/quake/packet" + "github.com/osm/quake/packet/svc" +) + +type Read struct { + Size uint32 + Packet packet.Packet +} + +func (cmd *Read) Bytes() []byte { + if cmd == nil || cmd.Packet == nil { + return []byte{} + } + + buf := buffer.New() + + buf.PutUint32(cmd.Size) + buf.PutBytes(cmd.Packet.Bytes()) + + return buf.Bytes() +} + +func parseRead(ctx *context.Context, buf *buffer.Buffer) (*Read, error) { + var err error + var cmd Read + + if cmd.Size, err = buf.GetUint32(); err != nil { + return nil, err + } + + bytes, err := buf.GetBytes(int(cmd.Size)) + if err != nil { + return nil, err + } + + if cmd.Packet, err = svc.Parse(ctx, bytes); err != nil { + return nil, err + } + + return &cmd, nil +} diff --git a/demo/mvd/set.go b/demo/mvd/set.go new file mode 100644 index 0000000..8cc4c95 --- /dev/null +++ b/demo/mvd/set.go @@ -0,0 +1,35 @@ +package mvd + +import ( + "github.com/osm/quake/common/buffer" + "github.com/osm/quake/common/context" +) + +type Set struct { + SeqOut uint32 + SeqIn uint32 +} + +func (cmd *Set) Bytes() []byte { + buf := buffer.New() + + buf.PutUint32(cmd.SeqOut) + buf.PutUint32(cmd.SeqIn) + + return buf.Bytes() +} + +func parseSet(ctx *context.Context, buf *buffer.Buffer) (*Set, error) { + var err error + var cmd Set + + if cmd.SeqOut, err = buf.GetUint32(); err != nil { + return nil, err + } + + if cmd.SeqIn, err = buf.GetUint32(); err != nil { + return nil, err + } + + return &cmd, nil +} diff --git a/demo/mvd/testdata/demo1.mvd b/demo/mvd/testdata/demo1.mvd Binary files differnew file mode 100644 index 0000000..052b266 --- /dev/null +++ b/demo/mvd/testdata/demo1.mvd diff --git a/demo/mvd/testdata/demo2.mvd b/demo/mvd/testdata/demo2.mvd Binary files differnew file mode 100644 index 0000000..c8f32e4 --- /dev/null +++ b/demo/mvd/testdata/demo2.mvd diff --git a/demo/mvd/testdata/demo3.mvd b/demo/mvd/testdata/demo3.mvd Binary files differnew file mode 100644 index 0000000..374af38 --- /dev/null +++ b/demo/mvd/testdata/demo3.mvd diff --git a/demo/mvd/testdata/demo4.mvd b/demo/mvd/testdata/demo4.mvd Binary files differnew file mode 100644 index 0000000..d2589ec --- /dev/null +++ b/demo/mvd/testdata/demo4.mvd diff --git a/demo/mvd/unknown.go b/demo/mvd/unknown.go new file mode 100644 index 0000000..ec0747a --- /dev/null +++ b/demo/mvd/unknown.go @@ -0,0 +1,25 @@ +package mvd + +import ( + "github.com/osm/quake/common/buffer" + "github.com/osm/quake/common/context" +) + +type Unknown struct { + Data []byte +} + +func (cmd *Unknown) Bytes() []byte { + return cmd.Data +} + +func parseUnknown(ctx *context.Context, buf *buffer.Buffer, size uint32) (*Unknown, error) { + var err error + var cmd Unknown + + if cmd.Data, err = buf.GetBytes(int(size)); err != nil { + return nil, err + } + + return &cmd, nil +} diff --git a/demo/mvd/usercommand.go b/demo/mvd/usercommand.go new file mode 100644 index 0000000..fc06b18 --- /dev/null +++ b/demo/mvd/usercommand.go @@ -0,0 +1,100 @@ +package mvd + +import ( + "github.com/osm/quake/common/buffer" + "github.com/osm/quake/common/context" +) + +type UserCommand struct { + size uint32 + + Data []byte + PlayerIndex byte + DropIndex byte + Msec byte + Angle [3]float32 + Forward uint16 + Side uint16 + Up uint16 + Buttons byte + Impulse byte +} + +func (cmd *UserCommand) Bytes() []byte { + if cmd.size != 23 { + return cmd.Data + } + + buf := buffer.New() + + buf.PutByte(cmd.PlayerIndex) + buf.PutByte(cmd.DropIndex) + buf.PutByte(cmd.Msec) + + for _, a := range cmd.Angle { + buf.PutFloat32(a) + } + + buf.PutUint16(cmd.Forward) + buf.PutUint16(cmd.Side) + buf.PutUint16(cmd.Up) + buf.PutByte(cmd.Buttons) + buf.PutByte(cmd.Impulse) + + return buf.Bytes() +} + +func parseUserCommand(ctx *context.Context, buf *buffer.Buffer, size uint32) (*UserCommand, error) { + var err error + var cmd UserCommand + + cmd.size = size + if cmd.size != 23 { + if cmd.Data, err = buf.GetBytes(int(cmd.size)); err != nil { + return nil, err + } + + goto end + } + + if cmd.PlayerIndex, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.DropIndex, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.Msec, err = buf.ReadByte(); err != nil { + return nil, err + } + + for i := 0; i < 3; i++ { + if cmd.Angle[i], err = buf.GetFloat32(); err != nil { + return nil, err + } + } + + if cmd.Forward, err = buf.GetUint16(); err != nil { + return nil, err + } + + if cmd.Side, err = buf.GetUint16(); err != nil { + return nil, err + } + + if cmd.Up, err = buf.GetUint16(); err != nil { + return nil, err + } + + if cmd.Buttons, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.Impulse, err = buf.ReadByte(); err != nil { + return nil, err + } + +end: + return &cmd, nil +} diff --git a/demo/mvd/weapon.go b/demo/mvd/weapon.go new file mode 100644 index 0000000..d7b6bf0 --- /dev/null +++ b/demo/mvd/weapon.go @@ -0,0 +1,71 @@ +package mvd + +import ( + "github.com/osm/quake/common/buffer" + "github.com/osm/quake/common/context" +) + +type Weapon struct { + PlayerIndex byte + Items uint32 + Shells byte + Nails byte + Rockets byte + Cells byte + Choice byte + String string +} + +func (cmd *Weapon) Bytes() []byte { + buf := buffer.New() + + buf.PutByte(cmd.PlayerIndex) + buf.PutUint32(cmd.Items) + buf.PutByte(cmd.Shells) + buf.PutByte(cmd.Nails) + buf.PutByte(cmd.Rockets) + buf.PutByte(cmd.Cells) + buf.PutByte(cmd.Choice) + buf.PutString(cmd.String) + + return buf.Bytes() +} + +func parseWeapon(ctx *context.Context, buf *buffer.Buffer, size uint32) (*Weapon, error) { + var err error + var cmd Weapon + + if cmd.PlayerIndex, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.Items, err = buf.GetUint32(); err != nil { + return nil, err + } + + if cmd.Shells, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.Nails, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.Rockets, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.Cells, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.Choice, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.String, err = buf.GetString(); err != nil { + return nil, err + } + + return &cmd, nil +} diff --git a/demo/mvd/weaponinstruction.go b/demo/mvd/weaponinstruction.go new file mode 100644 index 0000000..d923d1b --- /dev/null +++ b/demo/mvd/weaponinstruction.go @@ -0,0 +1,57 @@ +package mvd + +import ( + "github.com/osm/quake/common/buffer" + "github.com/osm/quake/common/context" +) + +type WeaponInstruction struct { + PlayerIndex byte + Bits byte + Seq uint32 + Mode uint32 + WeaponList []byte +} + +func (cmd *WeaponInstruction) Bytes() []byte { + buf := buffer.New() + + buf.PutByte(cmd.PlayerIndex) + buf.PutByte(cmd.Bits) + buf.PutUint32(cmd.Seq) + buf.PutUint32(cmd.Mode) + buf.PutBytes(cmd.WeaponList) + + return buf.Bytes() +} + +func parseWeaponInstruction( + ctx *context.Context, + buf *buffer.Buffer, + size uint32, +) (*WeaponInstruction, error) { + var err error + var cmd WeaponInstruction + + if cmd.PlayerIndex, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.Bits, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.Seq, err = buf.GetUint32(); err != nil { + return nil, err + } + + if cmd.Mode, err = buf.GetUint32(); err != nil { + return nil, err + } + + if cmd.WeaponList, err = buf.GetBytes(10); err != nil { + return nil, err + } + + return &cmd, nil +} diff --git a/demo/mvd/weaponserverside.go b/demo/mvd/weaponserverside.go new file mode 100644 index 0000000..36840e9 --- /dev/null +++ b/demo/mvd/weaponserverside.go @@ -0,0 +1,75 @@ +package mvd + +import ( + "github.com/osm/quake/common/buffer" + "github.com/osm/quake/common/context" +) + +type WeaponServerSide struct { + PlayerIndex byte + Items uint32 + Shells byte + Nails byte + Rockets byte + Cells byte + Choice byte + String string +} + +func (cmd *WeaponServerSide) Bytes() []byte { + buf := buffer.New() + + buf.PutByte(cmd.PlayerIndex) + buf.PutUint32(cmd.Items) + buf.PutByte(cmd.Shells) + buf.PutByte(cmd.Nails) + buf.PutByte(cmd.Rockets) + buf.PutByte(cmd.Cells) + buf.PutByte(cmd.Choice) + buf.PutString(cmd.String) + + return buf.Bytes() +} + +func parseWeaponServerSide( + ctx *context.Context, + buf *buffer.Buffer, + size uint32, +) (*WeaponServerSide, error) { + var err error + var cmd WeaponServerSide + + if cmd.PlayerIndex, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.Items, err = buf.GetUint32(); err != nil { + return nil, err + } + + if cmd.Shells, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.Nails, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.Rockets, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.Cells, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.Choice, err = buf.ReadByte(); err != nil { + return nil, err + } + + if cmd.String, err = buf.GetString(); err != nil { + return nil, err + } + + return &cmd, nil +} |
