Example #1
0
// Dumps the json representation of the new FlattenedSerializer Packets
func dumpSendTables(m *dota.CDemoSendTables) string {
	// This packet just contains a single large buffer
	r := newReader(m.GetData())

	// The buffer starts with a varint encoded length
	size := int(r.readVarUint32())
	if size != r.remBytes() {
		_panicf("expected %d additional bytes, got %d", size, r.remBytes())
	}

	// Read the rest of the buffer as a CSVCMsg_FlattenedSerializer.
	buf := r.readBytes(size)
	msg := &dota.CSVCMsg_FlattenedSerializer{}
	if err := proto.Unmarshal(buf, msg); err != nil {
		_panicf("cannot decode proto: %s", err)
	}

	str, _ := json.MarshalIndent(msg, "", "  ") // two space ident
	return string(str)
}
// Parses a CDemoSendTables packet
func (p *Parser) parseSendTables(m *dota.CDemoSendTables, pst *propertySerializerTable) *flattenedSerializers {
	// This packet just contains a single large buffer
	r := newReader(m.GetData())

	// The buffer starts with a varint encoded length
	size := r.readVarUint32()
	if size != r.remBytes() {
		_panicf("expected %d additional bytes, got %d", size, r.remBytes())
	}

	// Read the rest of the buffer as a CSVCMsg_FlattenedSerializer.
	buf := r.readBytes(size)
	msg := &dota.CSVCMsg_FlattenedSerializer{}
	if err := proto.Unmarshal(buf, msg); err != nil {
		_panicf("cannot decode proto: %s", err)
	}

	// Create the flattenedSerializers object and fill it
	fs := &flattenedSerializers{
		Serializers: make(map[string]map[int32]*dt),
		proto:       msg,
		pst:         pst,
		build:       p.GameBuild,
	}

	// Iterate through all flattened serializers and fill their properties
	for _, o := range msg.GetSerializers() {
		sName := msg.GetSymbols()[o.GetSerializerNameSym()]
		sVer := o.GetSerializerVersion()

		if fs.Serializers[sName] == nil {
			fs.Serializers[sName] = make(map[int32]*dt)
		}

		fs.Serializers[sName][sVer] = fs.recurseTable(o)
	}

	return fs
}
Example #3
0
// Parses a CDemoSendTables buffer, producing a sendTables object.
func parseSendTables(m *dota.CDemoSendTables) (*sendTables, error) {
	// This packet just contains a single large buffer
	r := newReader(m.GetData())

	// The buffer starts with a varint encoded length
	size := int(r.readVarUint32())
	if size != r.remBytes() {
		_panicf("expected %d additional bytes, got %d", size, r.remBytes())
	}

	// Read the rest of the buffer as a CSVCMsg_FlattenedSerializer.
	buf := r.readBytes(size)
	msg := &dota.CSVCMsg_FlattenedSerializer{}
	if err := proto.Unmarshal(buf, msg); err != nil {
		_panicf("cannot decode proto: %s", err)
	}

	// Create a list of sendProps
	props := make([]*sendProp, 0)
	for _, o := range msg.GetFields() {
		p := &sendProp{
			dtIndex:                o.GetVarTypeSym(),
			dtName:                 msg.GetSymbols()[o.GetVarTypeSym()],
			varIndex:               o.GetVarNameSym(),
			varName:                msg.GetSymbols()[o.GetVarNameSym()],
			bitCount:               o.BitCount,
			lowValue:               o.LowValue,
			highValue:              o.HighValue,
			fieldSerializerVersion: o.FieldSerializerVersion,
			sendNodeIndex:          o.GetSendNodeSym(),
			sendNodeName:           msg.GetSymbols()[o.GetSendNodeSym()],
		}

		if o.EncodeFlags != nil {
			p.encodeFlags = proto.Uint32(uint32(*o.EncodeFlags))
		}

		if o.FieldSerializerNameSym != nil {
			p.fieldSerializerIndex = o.FieldSerializerNameSym
			p.fieldSerializerName = proto.String(msg.GetSymbols()[o.GetFieldSerializerNameSym()])
		}

		props = append(props, p)
	}

	// Create a map of sendTables
	tables := make(map[string]*sendTable)
	for _, o := range msg.GetSerializers() {
		// Create the basic table.
		t := &sendTable{
			index:   o.GetSerializerNameSym(),
			name:    msg.GetSymbols()[o.GetSerializerNameSym()],
			version: o.GetSerializerVersion(),
			props:   make([]*sendProp, 0),
		}

		// Iterate through prop field indexes.
		for _, pid := range o.GetFieldsIndex() {
			// Get the property at the given index.
			prop := props[int(pid)]

			// If the prop has a serializer, inherit its properties
			if prop.fieldSerializerIndex != nil {
				// Find the serializer.
				ser, ok := tables[*prop.fieldSerializerName]
				if !ok {
					_panicf("unable to find serializer %d (%s)", *prop.fieldSerializerIndex, *prop.fieldSerializerName)
				}

				// Iterate through serializer props, adding them to the table.
				// Property names are subclassed as "%propVarName.%serializerVarName"
				for _, p := range ser.props {
					p2 := p.copy()
					p2.serializedFromIndex = prop.fieldSerializerIndex
					p2.serializedFromName = prop.fieldSerializerName
					p2.varName = _sprintf("%s.%s", prop.varName, p.varName)
					t.props = append(t.props, p2)
				}
				continue
			}

			// For normal props (without serializers), extract base type name
			// and element count, then store those as props in the table.
			typName, typCount, err := prop.typeInfo()
			if err != nil {
				_panicf("unable to flatten property %s: %s", prop.Describe(), err)
			}

			// Iterate through elements, adding them as new properties to the table.
			// Single element properties are named using the property var name.
			// Multiple element properties are named as "%propVarName.N".
			for i := 0; i < typCount; i++ {
				p2 := prop.copy()
				p2.dtName = typName
				if typCount > 1 {
					p2.varName = _sprintf("%s.%04d", prop.varName, i)
				}
				t.props = append(t.props, p2)
			}
		}

		tables[t.name] = t
	}

	// Return a sendTables object
	return &sendTables{tables: tables, props: props}, nil
}