demo

package
v1.0.303 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 6, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Index

Constants

View Source
const (
	MVDMagic          = 843339341 // {'M','V','D','2'}
	GZIPMagic         = 35615     // {0x8b, 0x1f}
	MaxStats          = 32        // playerstate stats uint32 bitmask
	MaxStatsExt       = 64        // extended playerstates supported
	MaxConfigStrings  = 2080      // CS_MAX
	MaxClients        = 256       // hard limit
	MaxEdicts         = 1024      // hard limit
	ProtocolMinimum   = 2009      // minor proto version required
	ProtocolCurrent   = 2010      // minor proto version
	ProtocolPlus      = 2011      // not sure this is used
	ProtocolPlusPlus  = 2012      // same
	ProtocolPlayerFog = 2013
	CommandBits       = 5
	CommandMask       = ((1 << CommandBits) - 1)
	ClientNumNone     = MaxClients - 1
	FlagExtLimits     = 1 << 2 // multiview flags extended limits
	FlagExtLimits2    = 1 << 3 // even more extended!!
)
View Source
const (
	MVDSvcBad = iota
	MVDSvcNop
	MVDSvcDisconnect
	MVDSvcReconnect
	MVDSvcServerData
	MVDSvcConfigString
	MVDSvcFrame
	MVDSvcFrameNoDelta
	MVDSvcUnicast
	MVDSvcUnicastReliable
	MVDSvcMulticastAll
	MVDSvcMulticastPHS
	MVDSvcMulticastPVS
	MVDSvcMulticastAllR
	MVDSvcMulticastPHSR
	MVDSvcMulticastPVSR
	MVDSvcSound
	MVDSvcPrint
	MVDSvcStuffText
	MVDSvcMax
)

Multi-view message types

View Source
const (
	SvcBad = iota
	SvcMuzzleFlash
	SvcMuzzleFlash2
	SvcTemporaryEntity
	SvcLayout
	SvcInventory
	SvcNoOperation
	SvcDisconnect
	SvcReconnect
	SvcSound
	SvcPrint
	SvcStuffText
	SvcServerData
	SvcConfigString
	SvcSpawnBaseline
	SvcCenterprint
	SvcDownload
	SvcPlayerInfo
	SvcPacketEntities
	SvcDeltaPacketEntities
	SvcFrame
	SvcMax
)

Regular demo message types

View Source
const (
	MvdPlayerType        = 1 << 0
	MvdPlayerOrigin      = 1 << 1
	MvdPlayerOrigin2     = 1 << 2
	MvdPlayerViewOffset  = 1 << 3
	MvdPlayerViewAngles  = 1 << 4
	MvdPlayerViewAngles2 = 1 << 5
	MvdPlayerKickAngles  = 1 << 6
	MvdPlayerBlend       = 1 << 7
	MvdPlayerFov         = 1 << 8
	MvdPlayerWeaponIndex = 1 << 9
	MvdPlayerWeaponFrame = 1 << 10
	MvdPlayerGunOffset   = 1 << 11
	MvdPlayerGunAngles   = 1 << 12
	MvdPlayerRdFlags     = 1 << 13
	MvdPlayerStats       = 1 << 14
	MvdPlayerRemove      = 1 << 15

	MvdPlayerMoreBits = 1 << 8

	MvdPlayerBits = 16
	MvdPlayerMask = (1 << MvdPlayerBits) - 1
)

Multi-view playerstate bit values

View Source
const (
	MvdPlayerFlagIgnoreGunIndex    = 1 << 0
	MvdPlayerFlagIgnoreGunFrames   = 1 << 1
	MvdPlayerFlagIgnoreBlend       = 1 << 2
	MvdPlayerFlagIgnoreViewAngles  = 1 << 3
	MvdPlayerFlagIgnoreDeltaAngles = 1 << 4
	MvdPlayerFlagIgnorePrediction  = 1 << 5
	MvdPlayerFlagExtensions        = 1 << 6
	MvdPlayerFlagExtensions2       = 1 << 7
	MvdPlayerFlagForce             = 1 << 8
	MvdPlayerFlagRemove            = 1 << 9
)

Multi-view playerstate flags

View Source
const (
	FlagNoMessages = 1 << 0
	FlagReverved1  = 1 << 1
	FlagReverved2  = 1 << 2
)

Multi-view stream flags (3 bits)

View Source
const (
	EntityStateLongSolid   = 1 << 3
	EntityStateUMask       = 1 << 4
	EntityStateBeamOrigin  = 1 << 5
	EntityStateShortAngles = 1 << 6
	EntityStateExtensions  = 1 << 7
	EntityStateExtensions2 = 1 << 8

	PlayerStateExtensions  = 1 << 6
	PlayerStateExtensions2 = 1 << 7
)

Multi-view entity bits

Variables

This section is empty.

Functions

This section is empty.

Types

type DM2Parser added in v1.0.233

type DM2Parser struct {
	// contains filtered or unexported fields
}

func NewDM2Demo added in v1.0.233

func NewDM2Demo(filename string) (*DM2Parser, error)

Read the entire binary demo file into memory

func (*DM2Parser) ApplyPacket added in v1.0.233

func (d *DM2Parser) ApplyPacket(packet *pb.Packet) error

ApplyPacket will add all the messages from the packet to the current demo.

func (*DM2Parser) GetTextProto added in v1.0.233

func (demo *DM2Parser) GetTextProto() *pb.DM2Demo

func (*DM2Parser) Marshal added in v1.0.233

func (demo *DM2Parser) Marshal() ([]byte, error)

Convert the textproto demo back into a quake 2 playable binary demo. The returned byte slice just needs to be written to a file as is.

func (*DM2Parser) NextPacket added in v1.0.233

func (demo *DM2Parser) NextPacket() (message.Buffer, int, error)

Demos are organized by "lumps" of data that are essentially packets. Even though all the data is already known, each lump represents a server packet's worth of game data. Each packet is prefixed with a 32 bit integer of the size of the packet and then a bunch of individual messages.

The default packet size for protocol 34 is 1390 bytes. Demos created by modern clients using protocols 35/36 will still write demos for protocol 34 to maximize compatability. Although it is possible to force these clients to record in their native protocol version.

func (*DM2Parser) RegisterCallback added in v1.0.233

func (p *DM2Parser) RegisterCallback(event int, dofunc func(any))

RegisterCallback allows for a custom function to be called at specific points while a demo is being parsed.

`event` is an index corresponding to what you want your callback to be associated with. These match up with the SVC* server messages.

`dofunc` is the function definition to be called at that event. The argument is set to `any` to accept any type, but this arg should be the parsed server message proto. Inside the dofunc, the arg will need to be casted to the appropriate type. Something like:

printMsg := argname.(*pb.Print)

func (*DM2Parser) Unmarshal added in v1.0.233

func (p *DM2Parser) Unmarshal() error

Load the binary demo into protobuf

func (*DM2Parser) UnregisterCallback added in v1.0.233

func (p *DM2Parser) UnregisterCallback(msgtype int)

Dynamically remove a particular callback

func (*DM2Parser) WriteTextProto added in v1.0.233

func (demo *DM2Parser) WriteTextProto(filename string) error

Turn a parsed demo structure back into a binary file

type MVD2Parser added in v1.0.262

type MVD2Parser struct {
	// contains filtered or unexported fields
}

This struct is the receiver used for parsing demo data.

func NewMVD2Parser added in v1.0.262

func NewMVD2Parser(f string) (*MVD2Parser, error)

Read the contents of the multi-view demo file and setup a receiver for parsing the data into textproto. The data is checked to make sure it's a valid demo file and the internal pointer set to just after the magic value.

Multi-view demo files can be deflated using GZIP (rfc1952) compression on the fly. Compression is detected using the file header and automatically uncompressed if utilized.

func (*MVD2Parser) GetDebug added in v1.0.274

func (p *MVD2Parser) GetDebug() bool

Private member accessor

func (*MVD2Parser) GetDemos added in v1.0.274

func (p *MVD2Parser) GetDemos() []*pb.MvdDemo

Private member accessor

func (*MVD2Parser) GetRawData added in v1.0.274

func (p *MVD2Parser) GetRawData() []byte

Private member accessor

func (*MVD2Parser) GetRawPosition added in v1.0.274

func (p *MVD2Parser) GetRawPosition() int

Private member accessor

func (*MVD2Parser) IsZipped added in v1.0.274

func (p *MVD2Parser) IsZipped() bool

Private member accessor

func (*MVD2Parser) NextPacket added in v1.0.262

func (p *MVD2Parser) NextPacket() (message.Buffer, error)

Demos are organized by shards of data that are essentially packets. Even though all the data is already known, each shard represents a server packet's worth of game data. Each packet is prefixed with a 16 bit integer of the size of the packet and then a bunch of individual messages in any particular order. Regular DM2 demos use 4 bytes for this value instead of 2.

There is no ending delimiter to the packet, the end of the last message is right up against the size value for the next packet. When the size value is 0 (0x0000), there are no more packets and the end of the demo has been reached. This is different from regular DM2 demos where a value of -1 (signed 0xffff) is the end of the demo.

func (*MVD2Parser) ParseConfigString added in v1.0.262

func (p *MVD2Parser) ParseConfigString(msg *message.Buffer, remap *pb.MvdConfigStringRemap) (*pb.ConfigString, error)

Parse a single configstring from MVD data

func (*MVD2Parser) ParseConfigStrings added in v1.0.262

func (p *MVD2Parser) ParseConfigStrings(msg *message.Buffer, remap *pb.MvdConfigStringRemap) map[int32]*pb.ConfigString

This parses the blob of configstrings that directly follow the serverdata at the beginning of the demo file.

The list of players in the demo is built using configstrings for skins. The cs_index - skin offset == the player number (0-maxclients), and the player name is the prefix of the skin string.

func (*MVD2Parser) ParseDeltaEntities added in v1.0.262

func (p *MVD2Parser) ParseDeltaEntities(msg *message.Buffer) (map[int32]*pb.PackedEntity, error)

Parse all the entities from a frame. These come directly after all the playerstates.

func (*MVD2Parser) ParseDeltaEntity added in v1.0.262

func (p *MVD2Parser) ParseDeltaEntity(msg *message.Buffer, bits int64, from *pb.PackedEntity) (*pb.PackedEntity, error)

Parse an individual edict_t. These are delta compressed (only changes from the last update are emitted); the PackedEntity proto returned merged with the previos version of this entity.

func (*MVD2Parser) ParseDeltaPlayer added in v1.0.262

func (p *MVD2Parser) ParseDeltaPlayer(msg *message.Buffer, bits uint32, flags int32) (*pb.PackedPlayer, error)

Parse a compressed player. Parsing delta players from regular DM2 demos is similar but not identical, so a separate func is needed.

func (*MVD2Parser) ParseEntityBits added in v1.0.262

func (p *MVD2Parser) ParseEntityBits(msg *message.Buffer) (int32, int64)

Each entity is prefixed with up to 5 bytes of bitmask followed by the entity number (up to 2 bytes) and then the actual data.

func (*MVD2Parser) ParseFrame added in v1.0.262

func (p *MVD2Parser) ParseFrame(msg *message.Buffer) (*pb.MvdFrame, error)

Each frame contains portal data, then all the player POVs (delta compressed), and then all the compressed entities.

func (*MVD2Parser) ParseMulticast added in v1.0.262

func (p *MVD2Parser) ParseMulticast(msg *message.Buffer, to int, extra int) *pb.MvdMulticast

ParseMulticast is used to parse all 6 multicast cmd types

func (*MVD2Parser) ParsePacket added in v1.0.262

func (p *MVD2Parser) ParsePacket(msg *message.Buffer) (*pb.MvdPacket, error)

Loop through all the messages included in this shard of data.

func (*MVD2Parser) ParsePacketPlayers added in v1.0.262

func (p *MVD2Parser) ParsePacketPlayers(msg *message.Buffer) (map[int32]*pb.PackedPlayer, error)

Read all the player info from a frame.

func (*MVD2Parser) ParsePlayerStats added in v1.0.262

func (p *MVD2Parser) ParsePlayerStats(msg *message.Buffer, flags int32) map[uint32]int32

Stats are a set of integer values at the end of each playerstate. They are are used to transfer rapidly changing values from server to client for displaying in the HUD. Score, health value, armor value, etc. These are transfered every server frame.

Some stats numbers are direct values (health, armor), and some are indexes to things like config string values.

func (*MVD2Parser) ParseServerData added in v1.0.262

func (p *MVD2Parser) ParseServerData(msg *message.Buffer, extra int) (*pb.MvdServerData, error)

ServerData is the first message in a demo, it contains info about what protocol versions were used at the time of the capture, the game directory, the client number of the dummy spec, and more.

func (*MVD2Parser) ParseSound added in v1.0.262

func (p *MVD2Parser) ParseSound(msg *message.Buffer, extra int) *pb.PackedSound

func (*MVD2Parser) ParseUnicast added in v1.0.262

func (p *MVD2Parser) ParseUnicast(msg *message.Buffer, reliable bool, extra int) (*pb.MvdUnicast, error)

func (*MVD2Parser) RegisterCallback added in v1.0.262

func (p *MVD2Parser) RegisterCallback(event int, dofunc func(any))

RegisterCallback allows for a custom function to be called at specific points while a demo is being parsed.

`event` is an index corresponding to what you want your callback to be associated with. These match up with the SVC* server messages.

`dofunc` is the function definition to be called at that event. The argument is set to `any` to accept any type, but this arg should be the parsed server message proto. Inside the dofunc, the arg will need to be casted to the appropriate type. Something like:

printMsg := argname.(*pb.Print)

func (*MVD2Parser) Unmarshal added in v1.0.262

func (p *MVD2Parser) Unmarshal() ([]*pb.MvdDemo, error)

Parse a demo file into one or more protobufs.

Each .mvd2 file can contain multiple "demos", each usually being a unique map. Recording a multi-view demo can survive a map change on the server, the demo will just contain another MvdServerData message with configstrings, playerstates and entity baselines.

Unmarshal will return a list of demo protos in event a .mvd2 file contains more than a single demo.

func (*MVD2Parser) UnregisterCallback added in v1.0.262

func (p *MVD2Parser) UnregisterCallback(msgtype int)

Dynamically remove a particular callback

type MVD2Writer added in v1.0.262

type MVD2Writer struct {
	// contains filtered or unexported fields
}

func NewMVD2Writer added in v1.0.262

func NewMVD2Writer(mvd *pb.MvdDemo) *MVD2Writer

Creates a new writer struct. All the proto-to-binary writing funcs use this struct as a receiver.

func (*MVD2Writer) Finalize added in v1.0.262

func (w *MVD2Writer) Finalize(name string) error

This is the final step when writing a demo. It will write all the binary data generated to a file named from the argument.

func (*MVD2Writer) Marshal added in v1.0.262

func (w *MVD2Writer) Marshal() error

This is the top level function for converting a textproto-based multi-view demo to it's proper binary format.

func (*MVD2Writer) MarshalConfigstring added in v1.0.262

func (w *MVD2Writer) MarshalConfigstring(data *pb.ConfigString) message.Buffer

func (*MVD2Writer) MarshalConfigstrings added in v1.0.262

func (w *MVD2Writer) MarshalConfigstrings(data map[int32]*pb.ConfigString) message.Buffer

func (*MVD2Writer) MarshalEntities added in v1.0.262

func (w *MVD2Writer) MarshalEntities(ents map[int32]*pb.PackedEntity) message.Buffer

func (*MVD2Writer) MarshalFrame added in v1.0.262

func (w *MVD2Writer) MarshalFrame(frame *pb.MvdFrame) message.Buffer

func (*MVD2Writer) MarshalMulticast added in v1.0.262

func (w *MVD2Writer) MarshalMulticast(mc *pb.MvdMulticast) (*message.Buffer, error)

Generate a binary buffer from a Multicast proto

func (*MVD2Writer) MarshalPlayer added in v1.0.262

func (w *MVD2Writer) MarshalPlayer(num int32, player *pb.PackedPlayer) message.Buffer

func (*MVD2Writer) MarshalPlayers added in v1.0.262

func (w *MVD2Writer) MarshalPlayers(players map[int32]*pb.PackedPlayer) message.Buffer

func (*MVD2Writer) MarshalServerData added in v1.0.262

func (w *MVD2Writer) MarshalServerData() message.Buffer

func (*MVD2Writer) MarshalSound added in v1.0.262

func (w *MVD2Writer) MarshalSound(sound *pb.PackedSound) (message.Buffer, error)

Generate a binary buffer from a PackedSound proto

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL