-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathplace_runner.rs
96 lines (80 loc) · 2.66 KB
/
place_runner.rs
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
use std::{
path::PathBuf,
process::{self, Command, Stdio},
sync::mpsc,
time::Duration,
};
use anyhow::{anyhow, bail, Context};
use fs_err as fs;
use fs_err::File;
use roblox_install::RobloxStudio;
use crate::{
message_receiver::{Message, MessageReceiver, MessageReceiverOptions, RobloxMessage},
plugin::RunInRbxPlugin,
};
/// A wrapper for process::Child that force-kills the process on drop.
struct KillOnDrop(process::Child);
impl Drop for KillOnDrop {
fn drop(&mut self) {
let _ignored = self.0.kill();
}
}
pub struct PlaceRunner {
pub port: u16,
pub place_path: PathBuf,
pub server_id: String,
pub lua_script: String,
}
impl PlaceRunner {
pub fn run(&self, sender: mpsc::Sender<Option<RobloxMessage>>) -> Result<(), anyhow::Error> {
let studio_install =
RobloxStudio::locate().context("Could not locate a Roblox Studio installation.")?;
let plugin_file_path = studio_install
.plugins_path()
.join(format!("run_in_roblox-{}.rbxmx", self.port));
let plugin = RunInRbxPlugin {
port: self.port,
server_id: &self.server_id,
lua_script: &self.lua_script,
};
let plugin_file = File::create(&plugin_file_path)?;
plugin.write(plugin_file)?;
let message_receiver = MessageReceiver::start(MessageReceiverOptions {
port: self.port,
server_id: self.server_id.to_owned(),
});
let _studio_process = KillOnDrop(
Command::new(studio_install.application_path())
.arg(format!("{}", self.place_path.display()))
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn()?,
);
let first_message = message_receiver
.recv_timeout(Duration::from_secs(60))
.ok_or_else(|| {
anyhow!("Timeout reached while waiting for Roblox Studio to come online")
})?;
match first_message {
Message::Start => {}
_ => bail!("Invalid first message received from Roblox Studio plugin"),
}
loop {
match message_receiver.recv() {
Message::Start => {}
Message::Stop => {
sender.send(None)?;
break;
}
Message::Messages(roblox_messages) => {
for message in roblox_messages.into_iter() {
sender.send(Some(message))?;
}
}
}
}
message_receiver.stop();
fs::remove_file(&plugin_file_path)?;
Ok(())
}
}