Skip to content

Commit e5131e0

Browse files
authored
Merge pull request #3 from VirxEC/qol
Various QoL things
2 parents dbcb896 + 79e8ade commit e5131e0

File tree

21 files changed

+900
-294
lines changed

21 files changed

+900
-294
lines changed

Cargo.toml

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
[workspace]
22
members = ["crates/rlbot", "crates/rlbot_flat"]
3-
resolver = "2"
3+
resolver = "3"
44
package.license-file = "LICENSE"
55
package.version = "0.1.0"
6+
7+
[profile.release]
8+
lto = "fat"
9+
opt-level = 3
10+
codegen-units = 1
11+
panic = "abort"
12+
13+
[profile.dev]
14+
opt-level = 3
15+
codegen-units = 1
16+
panic = "abort"

crates/rlbot/Cargo.toml

+5-13
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,19 @@
11
[package]
22
name = "rlbot"
33
version.workspace = true
4-
edition = "2021"
4+
edition = "2024"
55
license-file.workspace = true
66

77
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
88

9-
[profile.release]
10-
lto = "fat"
11-
opt-level = 3
12-
codegen-units = 1
13-
panic = "abort"
14-
15-
[profile.dev]
16-
opt-level = 3
17-
codegen-units = 1
18-
panic = "abort"
19-
209
[dependencies]
2110
kanal = { version = "0.1.0-pre8", default-features = false }
22-
thiserror = "1.0.50"
11+
thiserror = "2.0.12"
2312
rlbot_flat = { path = "../rlbot_flat" }
2413

2514
[features]
2615
default = ["glam"]
2716
glam = ["rlbot_flat/glam"]
17+
18+
[lints.clippy]
19+
all = "warn"

crates/rlbot/examples/atba_agent/bot.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[settings]
22
name = "Rust Example Bot (atba_agent)"
33
agent_id = "rlbot/rust-example/atba_agent"
4-
# looks_config = "looks.toml"
4+
# loadout_file = "loadout.toml"
55
run_command = "..\\..\\..\\..\\target\\release\\examples\\atba_agent.exe"
66
run_command_linux = "../../../../target/release/examples/atba_agent"
77
# rust_interface::agents::run_agents supports "non-hivemind" multithreading using one connection
+52-29
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,67 @@
1-
use std::f32::consts::PI;
1+
use std::{f32::consts::PI, sync::Arc};
22

33
use rlbot::{
4-
agents::{run_agents, Agent, PacketQueue},
5-
flat::{ConnectionSettings, ControllableInfo, ControllerState, PlayerInput},
6-
util::RLBotEnvironment,
74
RLBotConnection,
5+
agents::{Agent, run_agents},
6+
flat::{
7+
ControllableInfo, ControllerState, FieldInfo, GamePacket, MatchConfiguration, PlayerInput,
8+
},
9+
util::{PacketQueue, RLBotEnvironment},
810
};
911

12+
#[allow(dead_code)]
1013
struct AtbaAgent {
11-
controllable_info: ControllableInfo,
14+
index: u32,
15+
spawn_id: i32,
16+
team: u32,
17+
name: String,
18+
match_config: Arc<MatchConfiguration>,
19+
field_info: Arc<FieldInfo>,
1220
}
1321

1422
impl Agent for AtbaAgent {
15-
fn new(controllable_info: ControllableInfo) -> Self {
16-
Self { controllable_info }
23+
fn new(
24+
team: u32,
25+
controllable_info: ControllableInfo,
26+
match_config: Arc<MatchConfiguration>,
27+
field_info: Arc<FieldInfo>,
28+
_packet_queue: &mut PacketQueue,
29+
) -> Self {
30+
let name = match_config
31+
.player_configurations
32+
.iter()
33+
.find_map(|player| {
34+
if player.spawn_id == controllable_info.spawn_id {
35+
Some(player.name.clone())
36+
} else {
37+
None
38+
}
39+
})
40+
.unwrap();
41+
42+
Self {
43+
index: controllable_info.index,
44+
spawn_id: controllable_info.spawn_id,
45+
team,
46+
name,
47+
match_config,
48+
field_info,
49+
}
1750
}
18-
fn tick(&mut self, game_packet: &rlbot::flat::GamePacket, packet_queue: &mut PacketQueue) {
51+
52+
fn tick(&mut self, game_packet: &GamePacket, packet_queue: &mut PacketQueue) {
1953
let Some(ball) = game_packet.balls.first() else {
2054
// If theres no ball, theres nothing to chase, don't do anything
2155
return;
2256
};
2357

2458
// We're not in the gtp, skip this tick
25-
if game_packet.players.len() <= self.controllable_info.index as usize {
59+
if game_packet.players.len() <= self.index as usize {
2660
return;
2761
}
2862

2963
let target = &ball.physics;
30-
let car = game_packet
31-
.players
32-
.get(self.controllable_info.index as usize)
33-
.unwrap()
34-
.physics;
64+
let car = game_packet.players[self.index as usize].physics;
3565

3666
let bot_to_target_angle = f32::atan2(
3767
target.location.y - car.location.y,
@@ -53,17 +83,18 @@ impl Agent for AtbaAgent {
5383
controller.throttle = 1.;
5484

5585
packet_queue.push(PlayerInput {
56-
player_index: self.controllable_info.index,
86+
player_index: self.index,
5787
controller_state: controller,
5888
});
5989
}
6090
}
91+
6192
fn main() {
6293
let RLBotEnvironment {
6394
server_addr,
6495
agent_id,
6596
} = RLBotEnvironment::from_env();
66-
let agent_id = agent_id.unwrap_or("rlbot/rust-example/atba_agent".into());
97+
let agent_id = agent_id.unwrap_or_else(|| "rlbot/rust-example/atba_agent".into());
6798

6899
println!("Connecting");
69100

@@ -76,17 +107,9 @@ fn main() {
76107
// If the hivemind field is set to true, one instance of your bot will handle
77108
// all of the bots in a team.
78109

79-
// Blocking
80-
run_agents::<AtbaAgent>(
81-
ConnectionSettings {
82-
agent_id: agent_id.clone(),
83-
wants_ball_predictions: true,
84-
wants_comms: true,
85-
close_between_matches: true,
86-
},
87-
rlbot_connection,
88-
)
89-
.expect("run_agents crashed");
90-
91-
println!("Agent(s) with agent_id `{agent_id}` exited nicely")
110+
// Blocking.
111+
run_agents::<AtbaAgent>(agent_id.clone(), true, true, rlbot_connection)
112+
.expect("run_agents crashed");
113+
114+
println!("Agent(s) with agent_id `{agent_id}` exited nicely");
92115
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[settings]
2+
name = "Rust Example Bot (atba_hivemind)"
3+
agent_id = "rlbot/rust-example/atba_hivemind"
4+
# loadout_file = "loadout.toml"
5+
run_command = "..\\..\\..\\..\\target\\release\\examples\\atba_hivemind.exe"
6+
run_command_linux = "../../../../target/release/examples/atba_hivemind"
7+
hivemind = true
8+
9+
[details]
10+
description = "Rust always-towards-ball-agent."
11+
# fun_fact = ""
12+
# source_link = "https://github.com/swz-git/rust-interface"
13+
developer = ""
14+
language = "rust"
15+
# logo_file = "logo.png"
16+
# ALL POSSIBLE TAGS: 1v1, teamplay, goalie, hoops, dropshot, snow-day, spike-rush, heatseaker, memebot
17+
# NOTE: Only add the goalie tag if your bot only plays as a goalie; this directly contrasts with the teamplay tag!
18+
# NOTE: Only add a tag for a special game mode if you bot properly supports it
19+
tags = []
+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
use std::f32::consts::PI;
2+
3+
use rlbot::{
4+
RLBotConnection,
5+
flat::{
6+
ControllableTeamInfo, ControllerState, FieldInfo, GamePacket, MatchConfiguration,
7+
PlayerInput,
8+
},
9+
hivemind::{Hivemind, run_hivemind},
10+
util::{PacketQueue, RLBotEnvironment},
11+
};
12+
13+
#[allow(dead_code)]
14+
struct AtbaHivemind {
15+
indices: Vec<u32>,
16+
spawn_ids: Vec<i32>,
17+
team: u32,
18+
names: Vec<String>,
19+
match_config: MatchConfiguration,
20+
field_info: FieldInfo,
21+
}
22+
23+
impl Hivemind for AtbaHivemind {
24+
fn new(
25+
controllable_team_info: ControllableTeamInfo,
26+
match_config: MatchConfiguration,
27+
field_info: FieldInfo,
28+
_packet_queue: &mut PacketQueue,
29+
) -> Self {
30+
let names = match_config
31+
.player_configurations
32+
.iter()
33+
.filter_map(|player| {
34+
controllable_team_info
35+
.controllables
36+
.iter()
37+
.find_map(|controllable| {
38+
if controllable.spawn_id == player.spawn_id {
39+
Some(player.name.clone())
40+
} else {
41+
None
42+
}
43+
})
44+
})
45+
.collect();
46+
47+
let (indices, spawn_ids) = controllable_team_info
48+
.controllables
49+
.iter()
50+
.map(|controllable| (controllable.index, controllable.spawn_id))
51+
.unzip();
52+
53+
Self {
54+
indices,
55+
spawn_ids,
56+
team: controllable_team_info.team,
57+
names,
58+
match_config,
59+
field_info,
60+
}
61+
}
62+
63+
fn tick(&mut self, game_packet: GamePacket, packet_queue: &mut PacketQueue) {
64+
let Some(ball) = game_packet.balls.first() else {
65+
// If theres no ball, theres nothing to chase, don't do anything
66+
return;
67+
};
68+
69+
// We're not in the gtp, skip this tick
70+
if game_packet.players.len() <= self.indices[self.indices.len() - 1] as usize {
71+
return;
72+
}
73+
74+
for &index in &self.indices {
75+
let target = &ball.physics;
76+
let car = game_packet.players[index as usize].physics;
77+
78+
let bot_to_target_angle = f32::atan2(
79+
target.location.y - car.location.y,
80+
target.location.x - car.location.x,
81+
);
82+
83+
let mut bot_front_to_target_angle = bot_to_target_angle - car.rotation.yaw;
84+
85+
bot_front_to_target_angle = (bot_front_to_target_angle + PI).rem_euclid(2. * PI) - PI;
86+
87+
let mut controller = ControllerState::default();
88+
89+
if bot_front_to_target_angle > 0. {
90+
controller.steer = 1.;
91+
} else {
92+
controller.steer = -1.;
93+
}
94+
95+
controller.throttle = 1.;
96+
97+
packet_queue.push(PlayerInput {
98+
player_index: index,
99+
controller_state: controller,
100+
});
101+
}
102+
}
103+
}
104+
105+
fn main() {
106+
let RLBotEnvironment {
107+
server_addr,
108+
agent_id,
109+
} = RLBotEnvironment::from_env();
110+
let agent_id = agent_id.unwrap_or_else(|| "rlbot/rust-example/atba_hivemind".into());
111+
112+
println!("Connecting");
113+
114+
let rlbot_connection = RLBotConnection::new(&server_addr).expect("connection");
115+
116+
println!("Running!");
117+
118+
// The hivemind field in your bot.toml file decides if rlbot core is going to
119+
// start your bot as one or multiple instances of your binary/exe.
120+
// If the hivemind field is set to true, one instance of your bot will handle
121+
// all of the bots in a team.
122+
123+
// Blocking.
124+
run_hivemind::<AtbaHivemind>(agent_id.clone(), true, true, rlbot_connection)
125+
.expect("run_hivemind crashed");
126+
127+
println!("Hivemind with agent_id `{agent_id}` exited nicely");
128+
}

crates/rlbot/examples/atba_raw/bot.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[settings]
22
name = "Rust Example Bot (atba_raw)"
33
agent_id = "rlbot/rust-example/atba_raw"
4-
# looks_config = "looks.toml"
4+
# loadout_file = "loadout.toml"
55
run_command = "..\\..\\..\\..\\target\\release\\examples\\atba_raw.exe"
66
run_command_linux = "../../../../target/release/examples/atba_raw"
77
# the "raw" atba example doesn't support hivemind mode

crates/rlbot/examples/atba_raw/main.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
use std::f32::consts::PI;
22

33
use rlbot::{
4+
Packet, RLBotConnection,
45
flat::{ConnectionSettings, ControllerState, PlayerInput},
56
util::RLBotEnvironment,
6-
Packet, RLBotConnection,
77
};
88

99
fn main() {
1010
let RLBotEnvironment {
1111
server_addr,
1212
agent_id,
1313
} = RLBotEnvironment::from_env();
14-
let agent_id = agent_id.unwrap_or("rlbot/rust-example/atba_raw".into());
14+
let agent_id = agent_id.unwrap_or_else(|| "rlbot/rust-example/atba_raw".into());
1515

1616
let mut rlbot_connection = RLBotConnection::new(&server_addr).expect("connection");
1717

@@ -33,15 +33,15 @@ fn main() {
3333
let packet = rlbot_connection.recv_packet().unwrap();
3434
if let Packet::ControllableTeamInfo(x) = packet {
3535
break x;
36-
} else {
37-
packets_to_process.push(packet);
38-
continue;
3936
}
37+
38+
packets_to_process.push(packet);
4039
};
4140

42-
if controllable_team_info.controllables.len() != 1 {
43-
panic!("The raw atba example code does not support hiveminds, please disable the hivemind field in bot.toml")
44-
}
41+
assert!(
42+
controllable_team_info.controllables.len() == 1,
43+
"The raw atba example code does not support hiveminds, please disable the hivemind field in bot.toml"
44+
);
4545

4646
let controllable_info = controllable_team_info
4747
.controllables
@@ -53,7 +53,7 @@ fn main() {
5353
loop {
5454
let Packet::GamePacket(game_packet) = packets_to_process
5555
.pop()
56-
.unwrap_or(rlbot_connection.recv_packet().unwrap())
56+
.unwrap_or_else(|| rlbot_connection.recv_packet().unwrap())
5757
else {
5858
continue;
5959
};

0 commit comments

Comments
 (0)