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
use ffi::LiveDataPacket;
use ratelimit;
use rlbot::RLBot;
use rlbot_generated::rlbot::flat::GameTickPacket;
use std::error::Error;
use std::mem;
use std::time::{Duration, Instant};
/// An iterator-like object that yields packets from the game as they occur.
pub struct Packeteer<'a> {
rlbot: &'a RLBot,
ratelimiter: ratelimit::Limiter,
prev_game_time: f32,
}
impl<'a> Packeteer<'a> {
pub(crate) fn new(rlbot: &RLBot) -> Packeteer {
// The goal is never to miss any packets. But if we poll too often, the
// game crashes, so it's a fine line. With an interval of 3ms we can
// catch 333 updates per second. That should be plenty.
let ratelimiter = ratelimit::Builder::new()
.interval(Duration::from_millis(3))
.build();
Packeteer {
rlbot,
ratelimiter,
prev_game_time: 0.0,
}
}
/// Block until we receive the next unique
/// [`LiveDataPacket`](::ffi::LiveDataPacket), and then return it.
///
/// # Errors
///
/// This function returns an error if five seconds pass without a new
/// packet being received. The assumption is that the game froze or
/// crashed, and waiting longer will not help.
pub fn next(&mut self) -> Result<LiveDataPacket, Box<Error>> {
let started = Instant::now();
let mut packet = unsafe { mem::uninitialized() };
loop {
self.ratelimiter.wait();
self.rlbot.update_live_data_packet(&mut packet)?;
// Wait until another "tick" has happened so we don't return duplicate data.
let game_time = packet.GameInfo.TimeSeconds;
if game_time != self.prev_game_time {
self.prev_game_time = game_time;
break;
}
if Instant::now() - started > Duration::from_secs(5) {
return Err(From::from("no packet received after five seconds"));
}
}
Ok(packet)
}
/// Block until we receive the next unique
/// [`GameTickPacket`](::flat::GameTickPacket), and then return it.
///
/// # Errors
///
/// This function returns an error if ten seconds pass without a new
/// packet being received. The assumption is that the game froze or
/// crashed, and waiting longer will not help.
pub fn next_flatbuffer(&mut self) -> Result<GameTickPacket, Box<Error>> {
let started = Instant::now();
loop {
self.ratelimiter.wait();
if let Some(packet) = self.rlbot.update_live_data_packet_flatbuffer() {
// Wait until another "tick" has happened so we don't return duplicate data.
let game_time = packet
.gameInfo()
.ok_or("Missing gameInfo")?
.secondsElapsed();
if game_time != self.prev_game_time {
self.prev_game_time = game_time;
return Ok(packet);
}
}
if Instant::now() - started > Duration::from_secs(10) {
return Err(From::from("no packet received after ten seconds"));
}
}
}
}