Skip to content

Commit b0ff54d

Browse files
committed
feat(controller): add radar + improve critical error logging
1 parent c4b9cb2 commit b0ff54d

5 files changed

Lines changed: 403 additions & 22 deletions

File tree

controller/examples/mock_radar.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use std::{
2+
sync::mpsc,
3+
thread,
4+
time::Duration,
5+
};
6+
7+
use ratatui::text::Line;
8+
use utils_console::{
9+
self,
10+
RadarFrame,
11+
RadarPoint,
12+
};
13+
14+
fn main() {
15+
// Init logger and channels
16+
utils_console::init_logger().expect("logger");
17+
let (log_tx, log_rx) = mpsc::channel::<Vec<Line<'static>>>();
18+
let (radar_tx, radar_rx) = mpsc::channel::<RadarFrame>();
19+
20+
// Mock data producer
21+
thread::spawn(move || {
22+
let mut t: f32 = 0.0;
23+
loop {
24+
// Log some lines
25+
log::info!("[STATUS] Mock radar running");
26+
log::info!("Frame t={:.1}", t);
27+
28+
// Drain logger buffer and forward to TUI
29+
let logs = utils_console::get_and_clear_log_lines();
30+
let _ = log_tx.send(logs);
31+
32+
// Create moving points around player within bounds
33+
let mut points: Vec<RadarPoint> = Vec::new();
34+
for i in 0..20 {
35+
let a = t + (i as f32) * 0.31415926;
36+
let r = 100.0 + ((i * 47) as f32 % 300.0);
37+
let x = r * a.cos();
38+
let y = r * a.sin();
39+
let dz = (((i as i32) % 21) - 10) * 2;
40+
let health = (50 + ((i as i32 * 7 + (t as i32)) % 50)).max(1) as u32;
41+
points.push(RadarPoint { x, y, dz, health });
42+
}
43+
44+
let yaw_deg = (t * 30.0) % 360.0;
45+
let frame = RadarFrame { yaw_deg, points };
46+
let _ = radar_tx.send(frame);
47+
48+
t += 0.1;
49+
thread::sleep(Duration::from_millis(100));
50+
}
51+
});
52+
53+
// Run TUI until user quits with 'q'
54+
if let Err(e) = utils_console::run_tui(log_rx, radar_rx) {
55+
eprintln!("TUI error: {:?}", e);
56+
}
57+
}

controller/src/enhancements/player.rs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ impl PlayerSpyer {
2828
&self,
2929
states: &StateRegistry,
3030
actor_list: &Vec<(u64, Ptr64<dyn AActor>)>,
31-
players_data: &mut Vec<(StatePlayerInfo, u32, u32, i32)>,
31+
players_data: &mut Vec<(StatePlayerInfo, f32, u32, i32)>,
3232
) -> anyhow::Result<()> {
3333
let decrypt = states.resolve::<StateDecrypt>(())?;
3434
let pubg_handle = states.resolve::<StatePubgHandle>(())?;
@@ -77,10 +77,13 @@ impl PlayerSpyer {
7777
continue;
7878
}
7979

80-
let distance = ((player_info.position[0] - local_player_info.location[0]).powi(2)
80+
let distance_in_meters = (((player_info.position[0] - local_player_info.location[0])
81+
.powi(2)
8182
+ (player_info.position[1] - local_player_info.location[1]).powi(2)
8283
+ (player_info.position[2] - local_player_info.location[2]).powi(2))
83-
.sqrt() as u32;
84+
.sqrt())
85+
.round()
86+
/ 100.0;
8487

8588
let difference = [
8689
player_info.position[0] - local_player_info.location[0],
@@ -106,7 +109,7 @@ impl PlayerSpyer {
106109
angle_diff as i32
107110
};
108111

109-
players_data.push((player_info.clone(), distance, team_id, angle_diff));
112+
players_data.push((player_info.clone(), distance_in_meters, team_id, angle_diff));
110113
}
111114
Ok(())
112115
}
@@ -115,8 +118,9 @@ impl PlayerSpyer {
115118
impl Enhancement for PlayerSpyer {
116119
fn update(&mut self, ctx: &crate::UpdateContext) -> anyhow::Result<()> {
117120
let actor_lists = ctx.states.resolve::<StateActorLists>(())?;
121+
let local_player_info = ctx.states.resolve::<StateLocalPlayerInfo>(())?;
118122

119-
let mut players_data: Vec<(StatePlayerInfo, u32, u32, i32)> = Vec::new();
123+
let mut players_data: Vec<(StatePlayerInfo, f32, u32, i32)> = Vec::new();
120124

121125
let cached_actors = actor_lists.cached_actors();
122126
for (_actor_id, actor_list) in cached_actors {
@@ -134,16 +138,39 @@ impl Enhancement for PlayerSpyer {
134138

135139
players_data.dedup_by(|a, b| a.1 == b.1);
136140

141+
// Prepare radar frame points (keep logs as well)
142+
let mut radar_points: Vec<utils_console::RadarPoint> = Vec::new();
143+
137144
for (player_info, distance, team_id, angle) in players_data {
138145
log::info!(
139-
"Distance: {} Health: {} Angle: {} Team: {}",
146+
"Distance: {}m Health: {} Angle: {} Team: {}",
140147
distance,
141148
player_info.health,
142149
angle,
143150
team_id
144151
);
152+
153+
// Convert to horizontal x/y in meters relative to local player
154+
let dx = (player_info.position[0] - local_player_info.location[0]) as f32 / 100.0;
155+
let dy = (player_info.position[1] - local_player_info.location[1]) as f32 / 100.0;
156+
let dz =
157+
((player_info.position[2] - local_player_info.location[2]) / 100.0).round() as i32;
158+
radar_points.push(utils_console::RadarPoint {
159+
x: dx,
160+
y: dy,
161+
dz,
162+
health: player_info.health,
163+
});
145164
}
146165

166+
// Send radar frame
167+
let yaw_deg = local_player_info.rotation[1];
168+
let frame = utils_console::RadarFrame {
169+
yaw_deg,
170+
points: radar_points,
171+
};
172+
let _ = ctx.radar_tx.send(frame);
173+
147174
Ok(())
148175
}
149176
}

controller/src/main.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ mod enhancements;
3232

3333
pub struct UpdateContext<'a> {
3434
pub states: &'a StateRegistry,
35+
pub radar_tx: std::sync::mpsc::Sender<utils_console::RadarFrame>,
3536
}
3637

3738
pub struct Application {
@@ -41,6 +42,7 @@ pub struct Application {
4142
pub enhancements: Vec<Rc<RefCell<dyn Enhancement>>>,
4243

4344
pub frame_read_calls: usize,
45+
pub radar_tx: std::sync::mpsc::Sender<utils_console::RadarFrame>,
4446
}
4547

4648
impl Application {
@@ -49,6 +51,7 @@ impl Application {
4951

5052
let update_context = UpdateContext {
5153
states: &self.states,
54+
radar_tx: self.radar_tx.clone(),
5255
};
5356

5457
for enhancement in &self.enhancements {
@@ -81,14 +84,15 @@ fn main() {
8184
}
8285

8386
let (log_sender, log_receiver) = mpsc::channel::<Vec<Line<'static>>>();
87+
let (radar_sender, radar_receiver) = mpsc::channel::<utils_console::RadarFrame>();
8488

8589
let app_thread_handle = thread::spawn(move || {
86-
if let Err(err) = app_logic_thread(log_sender) {
90+
if let Err(err) = app_logic_thread(log_sender, radar_sender) {
8791
log::error!("Critical error in app logic thread: {:#}", err);
8892
}
8993
});
9094

91-
if let Err(e) = utils_console::run_tui(log_receiver) {
95+
if let Err(e) = utils_console::run_tui(log_receiver, radar_receiver) {
9296
log::error!("TUI exited with an error: {:?}", e);
9397
}
9498

@@ -99,7 +103,10 @@ fn main() {
99103
log::info!("Application terminated.");
100104
}
101105

102-
fn app_logic_thread(log_sender: mpsc::Sender<Vec<Line<'static>>>) -> anyhow::Result<()> {
106+
fn app_logic_thread(
107+
log_sender: mpsc::Sender<Vec<Line<'static>>>,
108+
radar_sender: mpsc::Sender<utils_console::RadarFrame>,
109+
) -> anyhow::Result<()> {
103110
let os_info = get_os_info()?;
104111

105112
let platform_info = if os_info.is_windows {
@@ -155,6 +162,7 @@ fn app_logic_thread(log_sender: mpsc::Sender<Vec<Line<'static>>>) -> anyhow::Res
155162
pubg: pubg.clone(),
156163
enhancements: vec![Rc::new(RefCell::new(PlayerSpyer {}))],
157164
frame_read_calls: 0,
165+
radar_tx: radar_sender.clone(),
158166
};
159167
let app = Rc::new(RefCell::new(app));
160168

utils/console/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,8 @@ pub use logger::{
1111
};
1212

1313
mod tui;
14-
pub use tui::run_tui;
14+
pub use tui::{
15+
run_tui,
16+
RadarFrame,
17+
RadarPoint,
18+
};

0 commit comments

Comments
 (0)