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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#![allow(missing_docs)]

use crate::flat;
pub use flat::TileState;
use smallvec::SmallVec;

/// The inputs that control a car.
#[derive(Default)]
pub struct ControllerState {
    /// -1 for full reverse, 1 for full forward
    pub throttle: f32,
    /// -1 for full left, 1 for full right
    pub steer: f32,
    /// -1 for nose down, 1 for nose up
    pub pitch: f32,
    /// -1 for full left, 1 for full right
    pub yaw: f32,
    /// -1 for roll left, 1 for roll right
    pub roll: f32,
    /// true if you want to press the jump button
    pub jump: bool,
    /// true if you want to press the boost button
    pub boost: bool,
    /// true if you want to press the handbrake button
    pub handbrake: bool,
}

pub struct Vector3 {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}

/// Expresses the rotation state of an object in Euler angles, with values in
/// radians.
pub struct Rotator {
    pub pitch: f32,
    pub yaw: f32,
    pub roll: f32,
}

/// Expresses the rotation state of an object.
/// Learn about quaternions here: https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
/// You can tinker with them here to build an intuition: https://quaternions.online/
pub struct Quaternion {
    pub x: f32,
    pub y: f32,
    pub z: f32,
    pub w: f32,
}

/// Represents contact between a car and the ball.
pub struct Touch {
    /// The name of the player involved with the touch.
    pub player_name: String,
    /// Seconds that had elapsed in the game when the touch occurred.
    pub game_seconds: f32,
    /// The point of contact for the touch.
    pub location: Vector3,
    /// The direction of the touch.
    pub normal: Vector3,
    /// The Team which the touch belongs to, 0 for blue 1 for orange.
    pub team: i32,
    pub(crate) _non_exhaustive: (),
}

pub struct ScoreInfo {
    pub score: i32,
    pub goals: i32,
    pub own_goals: i32,
    pub assists: i32,
    pub saves: i32,
    pub shots: i32,
    pub demolitions: i32,
    pub(crate) _non_exhaustive: (),
}

pub struct Physics {
    pub location: Vector3,
    pub rotation: Rotator,
    pub velocity: Vector3,
    pub angular_velocity: Vector3,
    pub(crate) _non_exhaustive: (),
}

pub struct PlayerInfo {
    pub physics: Physics,
    pub score_info: ScoreInfo,
    pub is_demolished: bool,
    /// True if your wheels are on the ground, the wall, or the ceiling. False
    /// if you're midair or turtling.
    pub has_wheel_contact: bool,
    pub is_supersonic: bool,
    pub is_bot: bool,
    /// True if the player has jumped. Falling off the ceiling / driving off the
    /// goal post does not count.
    pub jumped: bool,
    ///  True if player has double jumped. False does not mean you have a jump
    /// remaining, because the  aerial timer can run out, and that doesn't
    /// affect this flag.
    pub double_jumped: bool,
    pub name: String,
    pub team: i32,
    pub boost: i32,
    pub(crate) _non_exhaustive: (),
}

pub struct DropshotBallInfo {
    pub absorbed_force: f32,
    pub damage_index: i32,
    pub force_accum_recent: f32,
    pub(crate) _non_exhaustive: (),
}

pub struct BallInfo {
    pub physics: Physics,
    pub latest_touch: Option<Touch>,
    pub dropshot_info: Option<DropshotBallInfo>,
    pub(crate) _non_exhaustive: (),
}

pub struct BoostPadState {
    /// True if the boost can be picked up
    pub is_active: bool,
    /// The number of seconds since the boost has been picked up, or 0.0 if the
    /// boost is active.
    pub timer: f32,
    pub(crate) _non_exhaustive: (),
}

pub struct DropshotTile {
    pub tile_state: TileState,
    pub(crate) _non_exhaustive: (),
}

pub struct GameInfo {
    pub seconds_elapsed: f32,
    pub game_time_remaining: f32,
    pub is_overtime: bool,
    pub is_unlimited_time: bool,
    /// True when cars are allowed to move, and during the pause menu. False
    /// during replays.
    pub is_round_active: bool,
    /// True when the clock is paused due to kickoff, but false during kickoff
    /// countdown. In other words, it is true while cars can move during
    /// kickoff. Note that if both players sit still, game clock start and this
    /// will become false.
    pub is_kickoff_pause: bool,
    /// Turns true after final replay, the moment the 'winner' screen appears.
    /// Remains true during next match countdown. Turns false again the
    /// moment the 'choose team' screen appears.
    pub is_match_ended: bool,
    pub world_gravity_z: f32,
    /// Game speed multiplier, 1.0 is regular game speed.
    pub game_speed: f32,
    pub(crate) _non_exhaustive: (),
}

pub struct TeamInfo {
    pub team_index: i32,
    /// number of goals scored.
    pub score: i32,
    pub(crate) _non_exhaustive: (),
}

pub struct GameTickPacket {
    pub players: SmallVec<[PlayerInfo; 4]>,
    // Until generic const lands in Rust, we're limited to array sizes handpicked by smallvec.
    // Ideally this would be 34:
    pub boost_pad_states: SmallVec<[BoostPadState; 36]>,
    /// Info about the ball. This is usually present, but can be `None` at these
    /// times:
    ///
    /// - Briefly at the start of a goal replay
    /// - During PodiumSpotlight when the winning team is (ideally) celebrating.
    /// - Possibly at other times not during normal gameplay.
    pub ball: Option<BallInfo>,
    pub game_info: GameInfo,
    /// The state of each dropshot tile. This will be `None` if the current game
    /// is not a Dropshot game.
    // Ideally this would be 140:
    pub tile_information: Option<SmallVec<[DropshotTile; 256]>>,
    pub teams: SmallVec<[TeamInfo; 2]>,
    pub(crate) _non_exhaustive: (),
}

pub(crate) fn build_update_player_input(
    player_index: i32,
    controller_state: &ControllerState,
) -> flatbuffers::FlatBufferBuilder<'static> {
    let mut builder = flatbuffers::FlatBufferBuilder::new_with_capacity(64);

    let controller_state_args = flat::ControllerStateArgs {
        throttle: controller_state.throttle,
        steer: controller_state.steer,
        pitch: controller_state.pitch,
        yaw: controller_state.yaw,
        roll: controller_state.roll,
        jump: controller_state.jump,
        boost: controller_state.boost,
        handbrake: controller_state.handbrake,
    };
    let controller_state = flat::ControllerState::create(&mut builder, &controller_state_args);

    let args = flat::PlayerInputArgs {
        playerIndex: player_index,
        controllerState: Some(controller_state),
    };
    let player_input = flat::PlayerInput::create(&mut builder, &args);

    builder.finish(player_input, None);
    builder
}