Skip to content

Commit 3e0c4ac

Browse files
refactor: response handling trait
1 parent 1822843 commit 3e0c4ac

4 files changed

Lines changed: 259 additions & 28 deletions

File tree

src/cli/cli.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod server_subcommands;
22
mod local_subcommands;
33
mod input_waiter;
4+
mod response_handling;
45

56
use local_subcommands::{LocalSubcommands, handle_local_subcommand};
67
use server_subcommands::{ServerSubcommands, handle_server_subcommand};

src/cli/response_handling.rs

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
use rw3d_core::packet::WitcherPacket;
2+
use rw3d_core::utils::{scripts_execute_formatter, scripts_root_path_formatter, mod_list_formatter, opcode_formatter, var_list_formatter, scripts_reload_formatter, scripts_reload_response_type, ScriptsReloadResponseType};
3+
4+
5+
6+
pub(crate) trait HandleResponse {
7+
fn handle(&mut self, response: WitcherPacket, verbose_print: bool);
8+
fn should_exit(&self) -> bool;
9+
}
10+
11+
12+
13+
pub(crate) struct ScriptsReloadHandler {
14+
has_finished: bool,
15+
warnings: Vec<String>,
16+
errors: Vec<String>
17+
}
18+
19+
impl ScriptsReloadHandler {
20+
fn print_summary(&self) {
21+
println!("{} Errors, {} Warnings\n", self.errors.len(), self.warnings.len());
22+
23+
for e in &self.errors {
24+
println!("{}", e);
25+
}
26+
27+
println!(""); // empty line between errors and warnings
28+
29+
for w in &self.warnings {
30+
println!("{}", w);
31+
}
32+
}
33+
}
34+
35+
impl Default for ScriptsReloadHandler {
36+
fn default() -> Self {
37+
ScriptsReloadHandler {
38+
has_finished: false,
39+
warnings: Vec::new(),
40+
errors: Vec::new(),
41+
}
42+
}
43+
}
44+
45+
impl HandleResponse for ScriptsReloadHandler {
46+
fn handle(&mut self, response: WitcherPacket, verbose_print: bool) {
47+
let msg = scripts_reload_formatter(&response);
48+
49+
if let Ok(response_type) = scripts_reload_response_type(&response) {
50+
match response_type {
51+
ScriptsReloadResponseType::Started => {
52+
self.has_finished = false;
53+
}
54+
ScriptsReloadResponseType::Warn {..} => {
55+
self.warnings.push(msg.to_string());
56+
}
57+
ScriptsReloadResponseType::Error {..} => {
58+
self.errors.push(msg.to_string());
59+
}
60+
ScriptsReloadResponseType::Finished(_) => {
61+
self.has_finished = true;
62+
}
63+
_ => {}
64+
}
65+
}
66+
67+
if verbose_print {
68+
println!("{:?}", response);
69+
} else {
70+
println!("{}", msg);
71+
}
72+
73+
if self.has_finished && ( !self.warnings.is_empty() || !self.errors.is_empty() ) {
74+
self.print_summary();
75+
}
76+
}
77+
78+
fn should_exit(&self) -> bool {
79+
self.has_finished
80+
}
81+
}
82+
83+
84+
85+
pub(crate) struct ScriptsExecuteHandler();
86+
87+
impl HandleResponse for ScriptsExecuteHandler {
88+
fn handle(&mut self, response: WitcherPacket, verbose_print: bool) {
89+
if verbose_print {
90+
println!("{:?}", response);
91+
} else {
92+
println!("{}", scripts_execute_formatter(&response));
93+
}
94+
}
95+
96+
fn should_exit(&self) -> bool {
97+
true // only one packet
98+
}
99+
}
100+
101+
102+
103+
pub(crate) struct ScriptsRootpathHandler();
104+
105+
impl HandleResponse for ScriptsRootpathHandler {
106+
fn handle(&mut self, response: WitcherPacket, verbose_print: bool) {
107+
if verbose_print {
108+
println!("{:?}", response);
109+
} else {
110+
println!("{}", scripts_root_path_formatter(&response));
111+
}
112+
}
113+
114+
fn should_exit(&self) -> bool {
115+
true // only one packet
116+
}
117+
}
118+
119+
120+
121+
pub(crate) struct ModlistHandler();
122+
123+
impl HandleResponse for ModlistHandler {
124+
fn handle(&mut self, response: WitcherPacket, verbose_print: bool) {
125+
if verbose_print {
126+
println!("{:?}", response);
127+
} else {
128+
println!("{}", mod_list_formatter(&response));
129+
}
130+
}
131+
132+
fn should_exit(&self) -> bool {
133+
true // only one packet
134+
}
135+
}
136+
137+
138+
139+
pub(crate) struct OpcodeHandler();
140+
141+
impl HandleResponse for OpcodeHandler {
142+
fn handle(&mut self, response: WitcherPacket, verbose_print: bool) {
143+
if verbose_print {
144+
println!("{:?}", response);
145+
} else {
146+
println!("{}", opcode_formatter(&response));
147+
}
148+
}
149+
150+
fn should_exit(&self) -> bool {
151+
true // only one packet
152+
}
153+
}
154+
155+
156+
157+
pub(crate) struct VarlistHandler();
158+
159+
impl HandleResponse for VarlistHandler {
160+
fn handle(&mut self, response: WitcherPacket, verbose_print: bool) {
161+
if verbose_print {
162+
println!("{:?}", response);
163+
} else {
164+
println!("{}", var_list_formatter(&response));
165+
}
166+
}
167+
168+
fn should_exit(&self) -> bool {
169+
true // only one packet
170+
}
171+
}

src/cli/server_subcommands.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use std::{thread, net::{Shutdown, TcpStream}, sync::mpsc::{Receiver, TryRecvError}, time::Duration, io::Write};
22

33
use clap::Subcommand;
4-
use rw3d_core::utils::ResponseFormatter;
54

6-
use crate::{input_waiter::input_waiter, CliOptions};
5+
use crate::{input_waiter::input_waiter, CliOptions, response_handling::{HandleResponse, ScriptsReloadHandler, ScriptsExecuteHandler, ScriptsRootpathHandler, ModlistHandler, OpcodeHandler, VarlistHandler}};
76

87
/// Subcommands that require connection to game's socket and sending messages to it
98
#[derive(Subcommand)]
@@ -75,34 +74,33 @@ pub(crate) fn handle_server_subcommand( cmd: ServerSubcommands, options: CliOpti
7574
if !options.no_wait { thread::sleep( Duration::from_millis(1000) ) }
7675
println!("Handling the command...");
7776

78-
let formatter: ResponseFormatter;
77+
let handler: Box<dyn HandleResponse>;
7978
let p = match cmd {
8079
ServerSubcommands::Reload => {
81-
//TODO needs some summary and maybe colored text for errors
82-
// erros are not always displayed at the end and can be easily missed
83-
formatter = rw3d_core::utils::scripts_reload_formatter;
80+
//TODO maybe colored text for errors
81+
handler = Box::new(ScriptsReloadHandler::default());
8482
rw3d_core::commands::scripts_reload()
8583
}
8684
ServerSubcommands::Exec { cmd } => {
87-
formatter = rw3d_core::utils::scripts_execute_formatter;
85+
handler = Box::new(ScriptsExecuteHandler());
8886
rw3d_core::commands::scripts_execute(cmd)
8987
}
9088
ServerSubcommands::Rootpath => {
91-
formatter = rw3d_core::utils::scripts_root_path_formatter;
89+
handler = Box::new(ScriptsRootpathHandler());
9290
rw3d_core::commands::scripts_root_path()
9391
}
9492
ServerSubcommands::Modlist => {
9593
//TODO would be nice to have these mod actually sorted alphabetically at least
96-
formatter = rw3d_core::utils::mod_list_formatter;
94+
handler = Box::new(ModlistHandler());
9795
rw3d_core::commands::mod_list()
9896
}
9997
ServerSubcommands::Opcode { func_name, class_name } => {
100-
formatter = rw3d_core::utils::opcode_formatter;
98+
handler = Box::new(OpcodeHandler());
10199
rw3d_core::commands::opcode(func_name, class_name)
102100
}
103101
ServerSubcommands::Varlist { section, name } => {
104102
//TODO would be nice to have some option to sort those values
105-
formatter = rw3d_core::utils::var_list_formatter;
103+
handler = Box::new(VarlistHandler());
106104
rw3d_core::commands::var_list(section, name)
107105
}
108106
// ServerSubcommands::Varset { section, name, value } => {
@@ -131,7 +129,7 @@ pub(crate) fn handle_server_subcommand( cmd: ServerSubcommands, options: CliOpti
131129

132130
// This function can either finish by itself by the means of response timeout
133131
// or be stopped by input waiter thread if that one sends him a signal
134-
read_responses(&mut stream, options.response_timeout, reader_rcv, options.verbose, formatter);
132+
read_responses(&mut stream, options.response_timeout, reader_rcv, options.verbose, handler);
135133

136134
} else {
137135
// Wait a little bit to not finish the connection abruptly
@@ -172,7 +170,7 @@ fn try_connect(ip: String, max_tries: u8, tries_delay_ms: u64) -> Option<TcpStre
172170
None
173171
}
174172

175-
fn read_responses(stream: &mut TcpStream, response_timeout: i64, cancel_token: Receiver<()>, verbose_print: bool, formatter: ResponseFormatter) {
173+
fn read_responses(stream: &mut TcpStream, response_timeout: i64, cancel_token: Receiver<()>, verbose_print: bool, mut handler: Box<dyn HandleResponse>) {
176174
let mut peek_buffer = [0u8;6];
177175
let mut packet_available: bool;
178176
let mut response_wait_elapsed: i64 = 0;
@@ -204,10 +202,10 @@ fn read_responses(stream: &mut TcpStream, response_timeout: i64, cancel_token: R
204202
if packet_available {
205203
match rw3d_core::packet::WitcherPacket::from_stream(stream) {
206204
Ok(packet) => {
207-
if verbose_print {
208-
println!("{:?}", packet);
209-
} else {
210-
println!("{}", formatter(&packet));
205+
handler.handle(packet, verbose_print);
206+
207+
if handler.should_exit() {
208+
break;
211209
}
212210
}
213211
Err(e) => {

0 commit comments

Comments
 (0)