Skip to main content

subtr_actor/processor/
view.rs

1use super::*;
2
3/// Read-only processor surface consumed by collectors and stat calculators.
4///
5/// `ReplayProcessor` still owns replay traversal and actor-state mutation, but
6/// collectors should depend on this trait so the same collection pipeline can
7/// later be driven by non-replay state sources.
8pub trait ProcessorView {
9    fn get_replay_meta(&self) -> SubtrActorResult<ReplayMeta>;
10    fn get_replay_game_type_details(&self) -> ReplayGameTypeDetails {
11        self.get_replay_meta()
12            .map(|meta| meta.game_type)
13            .unwrap_or_default()
14    }
15    fn player_count(&self) -> usize;
16    fn iter_player_ids_in_order(&self) -> Box<dyn Iterator<Item = &PlayerId> + '_>;
17    fn current_in_game_team_player_counts(&self) -> [usize; 2];
18
19    fn get_seconds_remaining(&self) -> SubtrActorResult<i32>;
20    fn get_replicated_state_name(&self) -> SubtrActorResult<i32>;
21    fn get_replicated_game_state_time_remaining(&self) -> SubtrActorResult<i32>;
22    fn get_ball_has_been_hit(&self) -> SubtrActorResult<bool>;
23    fn get_ignore_ball_syncing(&self) -> SubtrActorResult<bool>;
24    fn get_team_scores(&self) -> SubtrActorResult<(i32, i32)>;
25    fn get_ball_hit_team_num(&self) -> SubtrActorResult<u8>;
26    fn get_scored_on_team_num(&self) -> SubtrActorResult<u8>;
27
28    fn get_normalized_ball_rigid_body(&self) -> SubtrActorResult<boxcars::RigidBody>;
29    fn get_velocity_applied_ball_rigid_body(
30        &self,
31        target_time: f32,
32    ) -> SubtrActorResult<boxcars::RigidBody>;
33    fn get_interpolated_ball_rigid_body(
34        &self,
35        target_time: f32,
36        close_enough_to_frame_time: f32,
37    ) -> SubtrActorResult<boxcars::RigidBody>;
38
39    fn get_normalized_player_rigid_body(
40        &self,
41        player_id: &PlayerId,
42    ) -> SubtrActorResult<boxcars::RigidBody>;
43    fn get_velocity_applied_player_rigid_body(
44        &self,
45        player_id: &PlayerId,
46        target_time: f32,
47    ) -> SubtrActorResult<boxcars::RigidBody>;
48    fn get_interpolated_player_rigid_body(
49        &self,
50        player_id: &PlayerId,
51        target_time: f32,
52        close_enough_to_frame_time: f32,
53    ) -> SubtrActorResult<boxcars::RigidBody>;
54
55    fn get_player_name(&self, player_id: &PlayerId) -> SubtrActorResult<String>;
56    fn get_player_car_hitbox(&self, player_id: &PlayerId) -> CarHitbox;
57    fn get_player_team_key(&self, player_id: &PlayerId) -> SubtrActorResult<String>;
58    fn get_player_is_team_0(&self, player_id: &PlayerId) -> SubtrActorResult<bool>;
59    fn get_player_id_from_car_id(&self, actor_id: &boxcars::ActorId) -> SubtrActorResult<PlayerId>;
60    fn get_player_boost_level(&self, player_id: &PlayerId) -> SubtrActorResult<f32>;
61    fn get_player_last_boost_level(&self, player_id: &PlayerId) -> SubtrActorResult<f32>;
62    fn get_player_boost_percentage(&self, player_id: &PlayerId) -> SubtrActorResult<f32>;
63    fn get_boost_active(&self, player_id: &PlayerId) -> SubtrActorResult<u8>;
64    fn get_jump_active(&self, player_id: &PlayerId) -> SubtrActorResult<u8>;
65    fn get_double_jump_active(&self, player_id: &PlayerId) -> SubtrActorResult<u8>;
66    fn get_dodge_active(&self, player_id: &PlayerId) -> SubtrActorResult<u8>;
67    fn get_powerslide_active(&self, player_id: &PlayerId) -> SubtrActorResult<bool>;
68    fn get_throttle(&self, player_id: &PlayerId) -> SubtrActorResult<u8>;
69    fn get_steer(&self, player_id: &PlayerId) -> SubtrActorResult<u8>;
70    fn get_dodge_impulse(&self, player_id: &PlayerId) -> SubtrActorResult<(f32, f32, f32)>;
71    fn get_dodge_torque(&self, player_id: &PlayerId) -> SubtrActorResult<(f32, f32, f32)>;
72    fn get_camera_pitch(&self, player_id: &PlayerId) -> SubtrActorResult<u8>;
73    fn get_camera_yaw(&self, player_id: &PlayerId) -> SubtrActorResult<u8>;
74    fn get_player_match_assists(&self, player_id: &PlayerId) -> SubtrActorResult<i32>;
75    fn get_player_match_goals(&self, player_id: &PlayerId) -> SubtrActorResult<i32>;
76    fn get_player_match_saves(&self, player_id: &PlayerId) -> SubtrActorResult<i32>;
77    fn get_player_match_score(&self, player_id: &PlayerId) -> SubtrActorResult<i32>;
78    fn get_player_match_shots(&self, player_id: &PlayerId) -> SubtrActorResult<i32>;
79
80    fn get_active_demos(&self) -> SubtrActorResult<Vec<DemolishAttribute>>;
81    fn demolishes(&self) -> &[DemolishInfo];
82    fn boost_pad_events(&self) -> &[BoostPadEvent];
83    fn touch_events(&self) -> &[TouchEvent];
84    fn dodge_refreshed_events(&self) -> &[DodgeRefreshedEvent];
85    fn dodge_refreshed_counter_available(&self) -> bool;
86    fn player_camera_events(&self) -> &[(PlayerId, PlayerCameraStateChange)];
87    fn player_stat_events(&self) -> &[PlayerStatEvent];
88    fn goal_events(&self) -> &[GoalEvent];
89    fn current_frame_active_demo_events(&self) -> &[DemoEventSample] {
90        &[]
91    }
92    fn current_frame_demolish_events(&self) -> &[DemolishInfo] {
93        &[]
94    }
95    fn current_frame_boost_pad_events(&self) -> &[BoostPadEvent];
96    fn current_frame_touch_events(&self) -> &[TouchEvent];
97    fn current_frame_dodge_refreshed_events(&self) -> &[DodgeRefreshedEvent];
98    fn current_frame_player_stat_events(&self) -> &[PlayerStatEvent];
99    fn current_frame_goal_events(&self) -> &[GoalEvent];
100}
101
102impl ProcessorView for ReplayProcessor<'_> {
103    fn get_replay_meta(&self) -> SubtrActorResult<ReplayMeta> {
104        ReplayProcessor::get_replay_meta(self)
105    }
106
107    fn get_replay_game_type_details(&self) -> ReplayGameTypeDetails {
108        ReplayProcessor::get_replay_game_type_details(self)
109    }
110
111    fn player_count(&self) -> usize {
112        ReplayProcessor::player_count(self)
113    }
114
115    fn iter_player_ids_in_order(&self) -> Box<dyn Iterator<Item = &PlayerId> + '_> {
116        Box::new(ReplayProcessor::iter_player_ids_in_order(self))
117    }
118
119    fn current_in_game_team_player_counts(&self) -> [usize; 2] {
120        ReplayProcessor::current_in_game_team_player_counts(self)
121    }
122
123    fn get_seconds_remaining(&self) -> SubtrActorResult<i32> {
124        ReplayProcessor::get_seconds_remaining(self)
125    }
126
127    fn get_replicated_state_name(&self) -> SubtrActorResult<i32> {
128        ReplayProcessor::get_replicated_state_name(self)
129    }
130
131    fn get_replicated_game_state_time_remaining(&self) -> SubtrActorResult<i32> {
132        ReplayProcessor::get_replicated_game_state_time_remaining(self)
133    }
134
135    fn get_ball_has_been_hit(&self) -> SubtrActorResult<bool> {
136        ReplayProcessor::get_ball_has_been_hit(self)
137    }
138
139    fn get_ignore_ball_syncing(&self) -> SubtrActorResult<bool> {
140        ReplayProcessor::get_ignore_ball_syncing(self)
141    }
142
143    fn get_team_scores(&self) -> SubtrActorResult<(i32, i32)> {
144        ReplayProcessor::get_team_scores(self)
145    }
146
147    fn get_ball_hit_team_num(&self) -> SubtrActorResult<u8> {
148        ReplayProcessor::get_ball_hit_team_num(self)
149    }
150
151    fn get_scored_on_team_num(&self) -> SubtrActorResult<u8> {
152        ReplayProcessor::get_scored_on_team_num(self)
153    }
154
155    fn get_normalized_ball_rigid_body(&self) -> SubtrActorResult<boxcars::RigidBody> {
156        ReplayProcessor::get_normalized_ball_rigid_body(self)
157    }
158
159    fn get_velocity_applied_ball_rigid_body(
160        &self,
161        target_time: f32,
162    ) -> SubtrActorResult<boxcars::RigidBody> {
163        ReplayProcessor::get_velocity_applied_ball_rigid_body(self, target_time)
164    }
165
166    fn get_interpolated_ball_rigid_body(
167        &self,
168        target_time: f32,
169        close_enough_to_frame_time: f32,
170    ) -> SubtrActorResult<boxcars::RigidBody> {
171        ReplayProcessor::get_interpolated_ball_rigid_body(
172            self,
173            target_time,
174            close_enough_to_frame_time,
175        )
176    }
177
178    fn get_normalized_player_rigid_body(
179        &self,
180        player_id: &PlayerId,
181    ) -> SubtrActorResult<boxcars::RigidBody> {
182        ReplayProcessor::get_normalized_player_rigid_body(self, player_id)
183    }
184
185    fn get_velocity_applied_player_rigid_body(
186        &self,
187        player_id: &PlayerId,
188        target_time: f32,
189    ) -> SubtrActorResult<boxcars::RigidBody> {
190        ReplayProcessor::get_velocity_applied_player_rigid_body(self, player_id, target_time)
191    }
192
193    fn get_interpolated_player_rigid_body(
194        &self,
195        player_id: &PlayerId,
196        target_time: f32,
197        close_enough_to_frame_time: f32,
198    ) -> SubtrActorResult<boxcars::RigidBody> {
199        ReplayProcessor::get_interpolated_player_rigid_body(
200            self,
201            player_id,
202            target_time,
203            close_enough_to_frame_time,
204        )
205    }
206
207    fn get_player_name(&self, player_id: &PlayerId) -> SubtrActorResult<String> {
208        ReplayProcessor::get_player_name(self, player_id)
209    }
210
211    fn get_player_car_hitbox(&self, player_id: &PlayerId) -> CarHitbox {
212        ReplayProcessor::get_player_car_hitbox(self, player_id)
213    }
214
215    fn get_player_team_key(&self, player_id: &PlayerId) -> SubtrActorResult<String> {
216        ReplayProcessor::get_player_team_key(self, player_id)
217    }
218
219    fn get_player_is_team_0(&self, player_id: &PlayerId) -> SubtrActorResult<bool> {
220        ReplayProcessor::get_player_is_team_0(self, player_id)
221    }
222
223    fn get_player_id_from_car_id(&self, actor_id: &boxcars::ActorId) -> SubtrActorResult<PlayerId> {
224        ReplayProcessor::get_player_id_from_car_id(self, actor_id)
225    }
226
227    fn get_player_boost_level(&self, player_id: &PlayerId) -> SubtrActorResult<f32> {
228        ReplayProcessor::get_player_boost_level(self, player_id)
229    }
230
231    fn get_player_last_boost_level(&self, player_id: &PlayerId) -> SubtrActorResult<f32> {
232        ReplayProcessor::get_player_last_boost_level(self, player_id)
233    }
234
235    fn get_player_boost_percentage(&self, player_id: &PlayerId) -> SubtrActorResult<f32> {
236        ReplayProcessor::get_player_boost_percentage(self, player_id)
237    }
238
239    fn get_boost_active(&self, player_id: &PlayerId) -> SubtrActorResult<u8> {
240        ReplayProcessor::get_boost_active(self, player_id)
241    }
242
243    fn get_jump_active(&self, player_id: &PlayerId) -> SubtrActorResult<u8> {
244        ReplayProcessor::get_jump_active(self, player_id)
245    }
246
247    fn get_double_jump_active(&self, player_id: &PlayerId) -> SubtrActorResult<u8> {
248        ReplayProcessor::get_double_jump_active(self, player_id)
249    }
250
251    fn get_dodge_active(&self, player_id: &PlayerId) -> SubtrActorResult<u8> {
252        ReplayProcessor::get_dodge_active(self, player_id)
253    }
254
255    fn get_powerslide_active(&self, player_id: &PlayerId) -> SubtrActorResult<bool> {
256        ReplayProcessor::get_powerslide_active(self, player_id)
257    }
258
259    fn get_throttle(&self, player_id: &PlayerId) -> SubtrActorResult<u8> {
260        ReplayProcessor::get_throttle(self, player_id)
261    }
262
263    fn get_steer(&self, player_id: &PlayerId) -> SubtrActorResult<u8> {
264        ReplayProcessor::get_steer(self, player_id)
265    }
266
267    fn get_dodge_impulse(&self, player_id: &PlayerId) -> SubtrActorResult<(f32, f32, f32)> {
268        ReplayProcessor::get_dodge_impulse(self, player_id)
269    }
270
271    fn get_dodge_torque(&self, player_id: &PlayerId) -> SubtrActorResult<(f32, f32, f32)> {
272        ReplayProcessor::get_dodge_torque(self, player_id)
273    }
274
275    fn get_camera_pitch(&self, player_id: &PlayerId) -> SubtrActorResult<u8> {
276        ReplayProcessor::get_camera_pitch(self, player_id)
277    }
278
279    fn get_camera_yaw(&self, player_id: &PlayerId) -> SubtrActorResult<u8> {
280        ReplayProcessor::get_camera_yaw(self, player_id)
281    }
282
283    fn get_player_match_assists(&self, player_id: &PlayerId) -> SubtrActorResult<i32> {
284        ReplayProcessor::get_player_match_assists(self, player_id)
285    }
286
287    fn get_player_match_goals(&self, player_id: &PlayerId) -> SubtrActorResult<i32> {
288        ReplayProcessor::get_player_match_goals(self, player_id)
289    }
290
291    fn get_player_match_saves(&self, player_id: &PlayerId) -> SubtrActorResult<i32> {
292        ReplayProcessor::get_player_match_saves(self, player_id)
293    }
294
295    fn get_player_match_score(&self, player_id: &PlayerId) -> SubtrActorResult<i32> {
296        ReplayProcessor::get_player_match_score(self, player_id)
297    }
298
299    fn get_player_match_shots(&self, player_id: &PlayerId) -> SubtrActorResult<i32> {
300        ReplayProcessor::get_player_match_shots(self, player_id)
301    }
302
303    fn get_active_demos(&self) -> SubtrActorResult<Vec<DemolishAttribute>> {
304        ReplayProcessor::get_active_demos(self).map(Iterator::collect)
305    }
306
307    fn demolishes(&self) -> &[DemolishInfo] {
308        &self.demolishes
309    }
310
311    fn boost_pad_events(&self) -> &[BoostPadEvent] {
312        &self.boost_pad_events
313    }
314
315    fn touch_events(&self) -> &[TouchEvent] {
316        &self.touch_events
317    }
318
319    fn dodge_refreshed_events(&self) -> &[DodgeRefreshedEvent] {
320        &self.dodge_refreshed_events
321    }
322
323    fn dodge_refreshed_counter_available(&self) -> bool {
324        self.cached_object_ids.dodges_refreshed_counter.is_some()
325    }
326
327    fn player_camera_events(&self) -> &[(PlayerId, PlayerCameraStateChange)] {
328        &self.player_camera_events
329    }
330
331    fn player_stat_events(&self) -> &[PlayerStatEvent] {
332        &self.player_stat_events
333    }
334
335    fn goal_events(&self) -> &[GoalEvent] {
336        &self.goal_events
337    }
338
339    fn current_frame_boost_pad_events(&self) -> &[BoostPadEvent] {
340        ReplayProcessor::current_frame_boost_pad_events(self)
341    }
342
343    fn current_frame_touch_events(&self) -> &[TouchEvent] {
344        ReplayProcessor::current_frame_touch_events(self)
345    }
346
347    fn current_frame_dodge_refreshed_events(&self) -> &[DodgeRefreshedEvent] {
348        ReplayProcessor::current_frame_dodge_refreshed_events(self)
349    }
350
351    fn current_frame_player_stat_events(&self) -> &[PlayerStatEvent] {
352        ReplayProcessor::current_frame_player_stat_events(self)
353    }
354
355    fn current_frame_goal_events(&self) -> &[GoalEvent] {
356        ReplayProcessor::current_frame_goal_events(self)
357    }
358}