1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
use crateStringTableError;
use crate*;
use crateHashMap;
/// Container managing all string tables in a replay.
///
/// String tables store game data in key-value pairs organized by table name.
///
/// # Examples
///
/// ## Iterating all tables
///
/// ```no_run
/// use source2_demo::prelude::*;
///
/// # fn example(ctx: &Context) {
/// for table in ctx.string_tables().iter() {
/// println!("Table: {} ({} rows)", table.name(), table.iter().count());
/// }
/// # }
/// ```
///
/// ## Accessing a specific table
///
/// ```no_run
/// use source2_demo::prelude::*;
///
/// # fn example(ctx: &Context) -> anyhow::Result<()> {
/// // Get by table name
/// let modifiers = ctx.string_tables().get_by_name("ActiveModifiers")?;
/// println!("Active modifiers: {}", modifiers.iter().count());
///
/// // Get by table ID
/// let table = ctx.string_tables().get_by_id(0)?;
/// println!("Table at index 0: {}", table.name());
/// # Ok(())
/// # }
/// ```
///
/// ## Extracting player data from userinfo
///
/// ```no_run
/// use source2_demo::prelude::*;
/// use source2_demo::proto::CMsgPlayerInfo;
///
/// # fn example(ctx: &Context) -> anyhow::Result<()> {
/// let userinfo = ctx.string_tables().get_by_name("userinfo")?;
///
/// // Read player info for slot 0
/// let player_row = userinfo.get_row_by_index(0)?;
/// if let Some(data) = player_row.value() {
/// let player_info = CMsgPlayerInfo::decode(data)?;
/// println!("Player: {}", player_info.name());
/// }
/// # Ok(())
/// # }
/// ```