func (helper *StateHelper) updateInstanceBaselineItem(item *StringTableItem) { classId, err := strconv.Atoi(item.Str) if err != nil { panic(err) } className := helper.ClassInfosNameMapping[classId] if className == "DT_DOTAPlayer" { return } mapping := helper.Mapping[classId] multiples := helper.Multiples[classId] if len(mapping) == 0 || len(multiples) == 0 { helper.pendingBaseline = append(helper.pendingBaseline, item) return } baseline, found := helper.Baseline[classId] if !found { baseline = map[string]interface{}{} helper.Baseline[classId] = baseline } br := utils.NewBitReader(item.Data) indices := br.ReadPropertiesIndex() baseValues := br.ReadPropertiesValues(mapping, multiples, indices) for key, value := range baseValues { baseline[key] = value } helper.Baseline[classId] = baseline }
func (p *Parser) ParsePacket(packet *parser.ParserBaseItem) { pe := (packet.Object).(*dota.CSVCMsg_PacketEntities) br := utils.NewBitReader(pe.GetEntityData()) currentIndex := -1 for i := 0; i < int(pe.GetUpdatedEntries()); i++ { currentIndex = br.ReadNextEntityIndex(currentIndex) switch ReadUpdateType(br) { case Preserve: p.EntityPreserve(br, currentIndex, packet.Tick) case Create: p.EntityCreate(br, currentIndex, packet.Tick) case Delete: p.EntityDelete(br, currentIndex, packet.Tick) } } }
func (p *Parser) ParsePacket(tick int, pe *dota.CSVCMsg_PacketEntities) { br := utils.NewBitReader(pe.GetEntityData()) currentIndex := -1 createPackets := []*packet_entities.PacketEntity{} preservePackets := []*packet_entities.PacketEntity{} deletePackets := []*packet_entities.PacketEntity{} for i := 0; i < int(pe.GetUpdatedEntries()); i++ { currentIndex = br.ReadNextEntityIndex(currentIndex) uType := packet_entities.ReadUpdateType(br) switch uType { case packet_entities.Create: createPackets = append(createPackets, p.entityCreate(br, currentIndex, tick)) case packet_entities.Preserve: preservePackets = append(preservePackets, p.entityPreserve(br, currentIndex, tick)) case packet_entities.Delete: deletePackets = append(deletePackets, p.entityDelete(br, currentIndex, tick)) } } for _, pe := range createPackets { p.Entities[pe.Index] = pe p.ByHandle[pe.Handle()] = pe if p.OnEntityCreated != nil { p.OnEntityCreated(pe) } } for _, pe := range preservePackets { if p.OnEntityPreserved != nil { p.OnEntityPreserved(pe) } } for _, pe := range deletePackets { if p.OnEntityDeleted != nil { p.OnEntityDeleted(pe) } // p.Entities[pe.Index] = nil // delete(p.ByHandle, pe.Handle()) } }
func NewParser(items parser.ParserBaseItems) { p := Parser{ entities: make([]*PacketEntity, 0, 2048), } var serverInfo *dota.CSVCMsg_ServerInfo packets := parser.ParserBaseItems{} for _, item := range items { switch value := item.Object.(type) { case *dota.CSVCMsg_ServerInfo: serverInfo = value case *dota.CSVCMsg_PacketEntities: if item.From == dota.EDemoCommands_DEM_Packet { packets = append(packets, item) } } } sort.Sort(packets) p.packets = packets p.classIdNumBits = int(math.Log(float64(serverInfo.GetMaxClasses()))/math.Log(2)) + 1 var classInfos *dota.CDemoClassInfo var instanceBaseline *dota.CDemoStringTablesTableT sendTables := map[string]*dota.CSVCMsg_SendTable{} for _, item := range items { switch value := item.Object.(type) { case *dota.CDemoClassInfo: if classInfos == nil { classInfos = value } case *dota.CSVCMsg_SendTable: sendTables[value.GetNetTableName()] = value case *dota.CDemoStringTables: for _, table := range value.GetTables() { if table.GetTableName() == "instancebaseline" { instanceBaseline = table } } } } for _, info := range classInfos.GetClasses() { id, name := int(info.GetClassId()), info.GetTableName() p.classInfosNameMapping[id] = name p.classInfosIdMapping[name] = id props := p.sendTablesHelper.LoadSendTable(name) p.mapping[id] = props m := map[string]int{} for _, prop := range props { m[prop.DtName+"."+prop.VarName] += 1 } p.multiples[id] = m } for _, item := range instanceBaseline.GetItems() { classId, err := strconv.Atoi(item.GetStr()) if err != nil { panic(err) } br := utils.NewBitReader(item.GetData()) indices := br.ReadPropertiesIndex() p.baseline[classId] = br.ReadPropertiesValues( p.mapping[classId], p.multiples[classId], indices, ) } }
func Parse(data []byte, numEntries, maxEntries, dataSizeBits int, dataFixedSize bool) map[int]*StringTableItem { br := utils.NewBitReader(data) bitsPerIndex := int(math.Log(float64(maxEntries)) / math.Log(2)) keyHistory := make([]string, 0, KeyHistorySize) result := map[int]*StringTableItem{} mysteryFlag := br.ReadBoolean() index := -1 nameBuf := "" for len(result) < numEntries { if br.ReadBoolean() { index++ } else { index = int(br.ReadUBits(bitsPerIndex)) } nameBuf = "" if br.ReadBoolean() { if mysteryFlag && br.ReadBoolean() { panic("mysteryFlag assertion failed!") } if br.ReadBoolean() { basis := br.ReadUBits(5) length := br.ReadUBits(5) if int(basis) >= len(keyHistory) { // spew.Dump("Ignoring invalid history index...", keyHistory, basis, length) nameBuf += br.ReadStringN(MaxNameLength) } else { s := keyHistory[basis] if int(length) > len(s) { spew.Dump(s, length) nameBuf += s + br.ReadStringN(int(MaxNameLength)) } else { nameBuf += s[0:length] + br.ReadStringN(int(MaxNameLength-length)) } } } else { nameBuf += br.ReadStringN(MaxNameLength) } if len(keyHistory) >= KeyHistorySize { copy(keyHistory[0:], keyHistory[1:]) keyHistory[len(keyHistory)-1] = "" // or the zero value of T keyHistory = keyHistory[:len(keyHistory)-1] } keyHistory = append(keyHistory, nameBuf) } value := []byte{} if br.ReadBoolean() { bitLength := 0 if dataFixedSize { bitLength = dataSizeBits } else { bitLength = int(br.ReadUBits(14) * 8) } value = append(value, br.ReadBitsAsBytes(bitLength)...) } result[index] = &StringTableItem{Str: nameBuf, Data: value} } return result }