// Internal parser for callback OnCDemoPacket, responsible for extracting // multiple inner packets from a single CDemoPacket. This is the main structure // that contains all other data types in the demo file. func (p *Parser) onCDemoPacket(m *dota.CDemoPacket) error { // Create a slice to store pending mesages. Messages are read first as // pending messages then sorted before dispatch. ms := make(pendingMessages, 0, 2) // Read all messages from the buffer. Messages are packed serially as // {type, size, data}. We keep reading until until less than a byte remains. r := newReader(m.GetData()) for r.remBytes() > 0 { t := int32(r.readUBitVar()) size := r.readVarUint32() buf := r.readBytes(size) ms = append(ms, &pendingMessage{p.Tick, t, buf}) } // Sort messages to ensure dependencies are met. For example, we need to // process string tables before game events that may reference them. sort.Sort(ms) // Dispatch messages in order, returning on handler error. for _, m := range ms { if err := p.Callbacks.callByPacketType(m.t, m.buf); err != nil { return err } } return nil }
// Internal parser for callback OnCDemoPacket, responsible for extracting // multiple inner packets from a single CDemoPacket. This is the main structure // that contains all other data types in the demo file. func (p *Parser) onCDemoPacket(m *dota.CDemoPacket) error { // Create a slice to store pending mesages. Messages are read first as // pending messages then sorted before dispatch. ms := make(pendingMessages, 0) // Read all messages from the buffer. Messages are packed serially as // {type, size, data}. We keep reading until until less than a byte remains. r := NewReader(m.GetData()) for r.remBytes() > 0 { t := int32(r.readUBitVar()) size := int(r.readVarUint32()) buf := r.readBytes(size) ms = append(ms, &pendingMessage{p.Tick, t, buf}) } // Sort messages to ensure dependencies are met. For example, we need to // process string tables before game events that may reference them. sort.Sort(ms) // Dispatch messages in order. for _, m := range ms { // Skip message we don't have a definition for (yet) // XXX TODO: remove this when we get updated protos. if m.t == 400 { continue } // Call each packet, panic if we encounter an error. // XXX TODO: this should return the error up the chain. Panic for debugging. if err := p.CallByPacketType(m.t, m.buf); err != nil { panic(err) } } return nil }