// OnCSVCMsg_Menu registers a callback for SVC_Messages_svc_Menu
773949
func (c *Callbacks) OnCSVCMsg_Menu(fn func(*dota.CSVCMsg_Menu) error) {
	c.onCSVCMsg_Menu = append(c.onCSVCMsg_Menu, fn)
}
1153266
func (c *Callbacks) OnCDOTAUserMsg_SendRoshanSpectatorPhase(fn func(*dota.CDOTAUserMsg_SendRoshanSpectatorPhase) error) {
	c.onCDOTAUserMsg_SendRoshanSpectatorPhase = append(c.onCDOTAUserMsg_SendRoshanSpectatorPhase, fn)
}
913202
func (c *Callbacks) OnCUserMessageShowMenu(fn func(*dota.CUserMessageShowMenu) error) {
	c.onCUserMessageShowMenu = append(c.onCUserMessageShowMenu, fn)
}
130127
func (p *Parser) onCSVCMsg_UpdateStringTable(m *dota.CSVCMsg_UpdateStringTable) error {
	// TODO: integrate
	t, ok := p.stringTables.Tables[m.GetTableId()]
	if !ok {
		_panicf("missing string table %d", m.GetTableId())
	}

	if v(5) {
		_debugf("tick=%d name=%s changedEntries=%d size=%d", p.Tick, t.name, m.GetNumChangedEntries(), len(m.GetStringData()))
	}

	// Parse the updates out of the string table data
	items := parseStringTable(m.GetStringData(), m.GetNumChangedEntries(), t.name, t.userDataFixedSize, t.userDataSize, t.flags)

	// Apply the updates to the parser state
	for _, item := range items {
		index := item.Index
		if _, ok := t.Items[index]; ok {
			if item.Key != "" && item.Key != t.Items[index].Key {
				t.Items[index].Key = item.Key
			}
			if len(item.Value) > 0 {
				t.Items[index].Value = item.Value
			}
		} else {
			t.Items[index] = item
		}
	}

	// Apply the updates to baseline state
	if t.name == "instancebaseline" {
		p.updateInstanceBaseline()
	}

	return nil
}
1226003
func (c *Callbacks) OnCSVCMsg_SplitScreen(fn func(*dota.CSVCMsg_SplitScreen) error) {
	c.onCSVCMsg_SplitScreen = append(c.onCSVCMsg_SplitScreen, fn)
}
115948
func (c *Callbacks) OnCDOTAUserMsg_MinimapEvent(fn func(*dota.CDOTAUserMsg_MinimapEvent) error) {
	c.onCDOTAUserMsg_MinimapEvent = append(c.onCDOTAUserMsg_MinimapEvent, fn)
}
827944
func (p *Parser) onCSVCMsg_ServerInfo(m *dota.CSVCMsg_ServerInfo) error {
	// This may be needed to parse PacketEntities.
	p.classIdSize = uint32(math.Log(float64(m.GetMaxClasses()))/math.Log(2)) + 1

	// Extract the build from the game dir.
	matches := gameBuildRegexp.FindStringSubmatch(m.GetGameDir())
	if len(matches) < 2 {
		return fmt.Errorf("unable to determine game build from '%s'", m.GetGameDir())
	}
	build, err := strconv.ParseUint(matches[1], 10, 32)
	if err != nil {
		return err
	}
	p.GameBuild = uint32(build)

	return nil
}
692252
func (sp *ServerPeer) subscribeRecvMsg(subscription spMsgSubscription) {
	sp.mtxSubscribers.Lock()
	defer sp.mtxSubscribers.Unlock()
	sp.recvSubscribers[subscription] = struct{}{}
}
1347342
func (c *Callbacks) OnCUserMessageShake(fn func(*dota.CUserMessageShake) error) {
	c.onCUserMessageShake = append(c.onCUserMessageShake, fn)
}
598950
func (c *Callbacks) OnCSVCMsg_Sounds(fn func(*dota.CSVCMsg_Sounds) error) {
	c.onCSVCMsg_Sounds = append(c.onCSVCMsg_Sounds, fn)
}
1281040
func (c *Callbacks) OnCSVCMsg_ClearAllStringTables(fn func(*dota.CSVCMsg_ClearAllStringTables) error) {
	c.onCSVCMsg_ClearAllStringTables = append(c.onCSVCMsg_ClearAllStringTables, fn)
}
788556
func (c *Callbacks) OnCUserMessageVoiceMask(fn func(*dota.CUserMessageVoiceMask) error) {
	c.onCUserMessageVoiceMask = append(c.onCUserMessageVoiceMask, fn)
}
862634
func (c *Callbacks) OnCUserMessageFade(fn func(*dota.CUserMessageFade) error) {
	c.onCUserMessageFade = append(c.onCUserMessageFade, fn)
}
110386
func (this *Weixinmp) CreateCustomMenu(btn *[]Button) error {
	var menu struct {
		Button *[]Button `json:"button"`
	}
	menu.Button = btn
	data, err := json.Marshal(&menu)
	if err != nil {
		return err
	}
	buf := bytes.NewBuffer(data)
	url := fmt.Sprintf("%smenu/create?access_token=", UrlPrefix)
	// retry
	for i := 0; i < retryNum; i++ {
		token, err := this.AccessToken.Fresh()
		if err != nil {
			if i < retryNum-1 {
				continue
			}
			return err
		}
		if _, err := post(url+token, "text/plain", buf); err != nil {
			if i < retryNum-1 {
				continue
			}
			return err
		}
		break // success
	}
	return nil
}
935198
func (c *Callbacks) OnCSVCMsg_CreateStringTable(fn func(*dota.CSVCMsg_CreateStringTable) error) {
	c.onCSVCMsg_CreateStringTable = append(c.onCSVCMsg_CreateStringTable, fn)
}
1314985
func (c *Callbacks) OnCDOTAUserMsg_ProjectionAbility(fn func(*dota.CDOTAUserMsg_ProjectionAbility) error) {
	c.onCDOTAUserMsg_ProjectionAbility = append(c.onCDOTAUserMsg_ProjectionAbility, fn)
}
1329575
func (c *Callbacks) OnCUserMessageVoiceSubtitle(fn func(*dota.CUserMessageVoiceSubtitle) error) {
	c.onCUserMessageVoiceSubtitle = append(c.onCUserMessageVoiceSubtitle, fn)
}