How can we have a console in a separate thread? #1150
-
I am looking to have a console which waits for input and passes that information for my main Bevy app to handle. But, I am completely unsure how to go about this. What would be the best way to make this work? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 5 replies
-
One simple way would probably be to read from Edit: Added code from #1150 (reply in thread) to accepted answer Code hidden to save spaceuse std::io::stdin;
use bevy::prelude::*;
use crossbeam_channel::{bounded, Receiver};
fn main() {
let (tx, rx) = bounded::<String>(1);
std::thread::spawn(move || loop {
let mut buf = String::new();
stdin().read_line(&mut buf).unwrap();
tx.send(buf).unwrap();
});
App::build()
.add_event::<StdinLine>()
.add_plugins(DefaultPlugins)
.add_thread_local_resource(StdinReceiver(rx))
.add_system_to_stage(stage::PRE_EVENT, read_stdin_system.system())
.add_system(log_stdin_system.system())
.run();
}
struct StdinReceiver(Receiver<String>);
struct StdinLine(String);
fn read_stdin_system(_: &mut World, resources: &mut Resources) {
let rx = resources.get_thread_local_mut::<StdinReceiver>().unwrap();
let mut events = resources.get_mut::<Events<StdinLine>>().unwrap();
if let Ok(line) = rx.0.try_recv() {
events.send(StdinLine(line));
}
}
fn log_stdin_system(mut reader: Local<EventReader<StdinLine>>, events: Res<Events<StdinLine>>) {
for line in reader.iter(&events) {
println!("Stdin gave {:?}", line.0);
}
} |
Beta Was this translation helpful? Give feedback.
-
I've attempted to put this together and I've come up with the preceding example. But, when I attempt to add a resource it states that it cannot be shared safely between threads. The only success I've had is adding a resource of |
Beta Was this translation helpful? Give feedback.
-
That is awesome, thank you! I got my example working by changing it to a One question about Bevy: Why do we have to have a reference to Completed example of the original code-snippet.
|
Beta Was this translation helpful? Give feedback.
One simple way would probably be to read from
stdin
, which normally gets flushed every time you press enter. E.g. you can use https://doc.rust-lang.org/std/io/trait.BufRead.html#method.read_line onstd::io::stdin()
.For that you'd need to create a seperate thread (before calling
App::run
), and then use a channel to send the data into bevy, via putting the channel in a resource. See https://stackoverflow.com/questions/30012995/how-can-i-read-non-blocking-from-stdinEdit: Added code from #1150 (reply in thread) to accepted answer
Code hidden to save space