|
| 1 | +# Parsing & handling custom net-messages |
| 2 | + |
| 3 | +## Finding interesting messages |
| 4 | + |
| 5 | +You can use the build tag `debugdemoinfocs` to find interesting net-messages. |
| 6 | + |
| 7 | +Example: `go run myprogram.go -tags debugdemoinfocs | grep "UnhandledMessage" | sort | uniq -c` |
| 8 | + |
| 9 | +<details> |
| 10 | +<summary>Sample output</summary> |
| 11 | + |
| 12 | +``` |
| 13 | + 1 UnhandledMessage: id=10 name=svc_ClassInfo |
| 14 | + 1 UnhandledMessage: id=14 name=svc_VoiceInit |
| 15 | + 9651 UnhandledMessage: id=17 name=svc_Sounds |
| 16 | + 1 UnhandledMessage: id=18 name=svc_SetView |
| 17 | + 227 UnhandledMessage: id=21 name=svc_BSPDecal |
| 18 | + 12705 UnhandledMessage: id=27 name=svc_TempEntities |
| 19 | + 514 UnhandledMessage: id=28 name=svc_Prefetch |
| 20 | + 85308 UnhandledMessage: id=4 name=net_Tick |
| 21 | + 2 UnhandledMessage: id=5 name=net_StringCmd |
| 22 | + 3 UnhandledMessage: id=6 name=net_SetConVar |
| 23 | + 3 UnhandledMessage: id=7 name=net_SignonState |
| 24 | + 1 UnhandledMessage: id=8 name=svc_ServerInfo |
| 25 | +``` |
| 26 | +</details> |
| 27 | + |
| 28 | +## Configuring a `NetMessageCreator` |
| 29 | + |
| 30 | +NetMessageCreators are needed for creating instances of net-messages that aren't parsed by default. |
| 31 | + |
| 32 | +You need to add them to the `ParserConfig.AdditionalNetMessageCreators` map where the key is the message-ID as seen in the debug output. |
| 33 | + |
| 34 | +Example: `ConVar` messages |
| 35 | + |
| 36 | +```go |
| 37 | +import ( |
| 38 | + dem "github.com/markus-wa/demoinfocs-golang" |
| 39 | + msg "github.com/markus-wa/demoinfocs-golang/msg" |
| 40 | +) |
| 41 | + |
| 42 | +cfg := dem.DefaultParserConfig |
| 43 | +cfg.AdditionalNetMessageCreators = map[int]dem.NetMessageCreator{ |
| 44 | + 6: func() proto.Message { |
| 45 | + return new(msg.CNETMsg_SetConVar) |
| 46 | + }, |
| 47 | +} |
| 48 | +``` |
| 49 | + |
| 50 | +## Registering net-message handlers |
| 51 | + |
| 52 | +To register a handler for net-messages `Parser.RegisterNetMessageHandler()` can be used. |
| 53 | + |
| 54 | +When using `Parser.ParseToEnd()` net-messages and events are dispatched asynchronously. To get around this you can use `Parser.ParseNextFrame()` instead. |
| 55 | + |
| 56 | +Example: |
| 57 | + |
| 58 | +```go |
| 59 | +p.RegisterNetMessageHandler(func(m *msg.CNETMsg_SetConVar) { |
| 60 | + for _, cvar := range m.Convars.Cvars { |
| 61 | + fmt.Println(fmt.Sprintf("cvar %s=%s", cvar.Name, cvar.Value)) |
| 62 | + } |
| 63 | +}) |
| 64 | +``` |
| 65 | + |
| 66 | +<details> |
| 67 | +<summary>Sample output</summary> |
| 68 | + |
| 69 | +``` |
| 70 | +cvar mp_spec_swapplayersides=1 |
| 71 | +cvar cash_team_rescued_hostage=750 |
| 72 | +cvar bot_autodifficulty_threshold_high=0 |
| 73 | +cvar cash_team_win_by_defusing_bomb=3500 |
| 74 | +cvar game_mode=1 |
| 75 | +cvar sv_damage_print_enable=0 |
| 76 | +cvar mp_force_pick_time=160 |
| 77 | +cvar mp_ggtr_bomb_pts_for_upgrade=2 |
| 78 | +cvar bot_quota=0 |
| 79 | +cvar ff_damage_reduction_bullets=0.33 |
| 80 | +cvar sv_gameinstructor_disable=1 |
| 81 | +cvar =0 |
| 82 | +cvar bot_quota_mode=fill |
| 83 | +cvar mp_join_grace_time=30 |
| 84 | +cvar mp_maxrounds=30 |
| 85 | +cvar ammo_grenade_limit_total=4 |
| 86 | +cvar mp_spectators_max=10 |
| 87 | +cvar mp_round_restart_delay=5 |
| 88 | +cvar mp_win_panel_display_time=15 |
| 89 | +cvar mp_respawn_immunitytime=0 |
| 90 | +cvar mp_roundtime_defuse=1.92 |
| 91 | +cvar mp_ggprogressive_round_restart_delay=15 |
| 92 | +cvar mp_match_end_restart=1 |
| 93 | +cvar mp_timelimit=0 |
| 94 | +cvar mp_warmuptime=5 |
| 95 | +cvar mp_randomspawn_los=0 |
| 96 | +cvar sv_competitive_official_5v5=1 |
| 97 | +cvar sv_mincmdrate=30 |
| 98 | +cvar mp_halftime_duration=15 |
| 99 | +cvar mp_weapons_allow_map_placed=1 |
| 100 | +cvar mp_autokick=0 |
| 101 | +cvar sv_grenade_trajectory_time_spectator=1 |
| 102 | +cvar sv_minrate=20000 |
| 103 | +cvar sv_holiday_mode=0 |
| 104 | +cvar sv_kick_players_with_cooldown=0 |
| 105 | +cvar mp_ggtr_bomb_defuse_bonus=1 |
| 106 | +cvar spec_freeze_time=5 |
| 107 | +cvar mp_buytime=15 |
| 108 | +cvar bot_difficulty=2 |
| 109 | +cvar mp_playerid_delay=0.5 |
| 110 | +cvar mp_roundtime_hostage=1.92 |
| 111 | +cvar mp_freezetime=15 |
| 112 | +cvar sv_maxcmdrate=128 |
| 113 | +cvar bot_defer_to_human_goals=1 |
| 114 | +cvar sv_skyname=sky_cs15_daylight01_hdr |
| 115 | +cvar mp_friendlyfire=1 |
| 116 | +cvar cash_team_hostage_interaction=150 |
| 117 | +cvar spec_freeze_panel_extended_time=0 |
| 118 | +cvar ff_damage_reduction_other=0.4 |
| 119 | +cvar sv_allow_wait_command=0 |
| 120 | +cvar mp_molotovusedelay=0 |
| 121 | +cvar mp_playerid_hold=0.25 |
| 122 | +cvar mp_limitteams=0 |
| 123 | +cvar cash_team_elimination_hostage_map_t=3000 |
| 124 | +cvar sv_friction=4.8 |
| 125 | +cvar mp_ggtr_bomb_detonation_bonus=1 |
| 126 | +cvar ammo_grenade_limit_flashbang=2 |
| 127 | +cvar sv_coaching_enabled=1 |
| 128 | +cvar steamworks_sessionid_server=1169494819006 |
| 129 | +cvar mp_overtime_enable=1 |
| 130 | +cvar tv_snapshotrate=24 |
| 131 | +cvar mp_roundtime=1.92 |
| 132 | +cvar sv_kick_ban_duration=0 |
| 133 | +cvar mp_halftime=1 |
| 134 | +cvar sv_spawn_afk_bomb_drop_time=30 |
| 135 | +cvar mp_ggtr_bomb_respawn_delay=0 |
| 136 | +cvar mp_overtime_startmoney=16000 |
| 137 | +cvar think_limit=0 |
| 138 | +cvar sv_accelerate=5.6 |
| 139 | +cvar ff_damage_reduction_grenade=0.85 |
| 140 | +cvar cash_team_elimination_hostage_map_ct=3000 |
| 141 | +cvar sv_maxupdaterate=128 |
| 142 | +cvar cash_team_hostage_alive=150 |
| 143 | +cvar tv_transmitall=1 |
| 144 | +cvar steamworks_sessionid_server=0 |
| 145 | +cvar steamworks_sessionid_server=1169497558498 |
| 146 | +``` |
| 147 | +</details> |
0 commit comments