Skip to content

Commit 8a9101a

Browse files
Merge pull request #10 from SpontanCombust:dev
v0.7.0
2 parents cff85d5 + 95c5eeb commit 8a9101a

9 files changed

Lines changed: 80 additions & 33 deletions

File tree

Cargo.lock

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ members = ["crates/*"]
33
resolver = "2"
44

55
[workspace.package]
6-
version = "0.6.0"
6+
version = "0.7.0"
77
edition = "2021"
88
authors = ["SpontanCombust"]
99

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2022 Przemysław Cedro
3+
Copyright (c) 2022 - 2024 Przemysław Cedro
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ Recompile game scripts.
3030
rw3d_cli.exe reload
3131
```
3232

33+
Recompile game scripts while developing a mod using REDkit.
34+
```ps1
35+
rw3d_cli.exe --target=editor reload
36+
```
37+
3338
Remotely call an exec function from the game. Remember to use quotation marks for the command argument.
3439
```ps1
3540
rw3d_cli.exe exec "spawn('Nekker', 3)"

crates/cli/src/main.rs

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,38 @@ struct Cli {
2323
#[derive(Parser)]
2424
pub(crate) struct CliOptions {
2525
/// IPv4 address of the machine on which the game is run.
26-
#[clap(long, default_value="127.0.0.1")]
26+
#[clap(long, default_value="127.0.0.1", display_order=0)]
2727
ip: String,
2828

29+
/// Select connection target
30+
#[clap(long, value_enum, default_value="game", display_order=1)]
31+
target: ConnectionTarget,
32+
33+
/// The maximum amount of milliseconds that program should wait for the game to respond.
34+
/// It will also affect how quickly the program shuts down.
35+
#[clap(long, short='t', default_value_t=2000, display_order=2)]
36+
response_timeout: u64,
37+
38+
/// Execute command immediately without doing short breaks between info messages beforehand.
39+
#[clap(long, display_order=3)]
40+
no_delay: bool,
41+
2942
/// Specify what logs are allowed to be printed to the standard output.
3043
/// Does not apply to output from the `scriptslog` command.
31-
#[clap(long, short='l', value_enum, default_value="all")]
44+
#[clap(long, short='l', value_enum, default_value="all", display_order=4)]
3245
log_level: LogLevel,
3346

3447
/// Enable verbose printing of packet contents.
35-
#[clap(long, short='v')]
48+
#[clap(long, short='v', display_order=5)]
3649
verbose: bool,
50+
}
3751

38-
/// Execute command immediately without doing short breaks between info messages beforehand.
39-
#[clap(long)]
40-
no_delay: bool,
41-
42-
/// The maximum amount of milliseconds that program should wait for the game to respond.
43-
/// It will also affect how quickly the program shuts down.
44-
#[clap(long, short='t', default_value_t=2000)]
45-
response_timeout: u64,
52+
#[derive(Debug, ArgEnum, Clone, Copy, PartialEq, Eq)]
53+
enum ConnectionTarget {
54+
/// Connect to the game running on its own
55+
Game,
56+
/// Connect to the game running through REDkit editor
57+
Editor
4658
}
4759

4860
#[derive(Debug, ArgEnum, Clone, Copy, PartialEq, Eq)]

crates/cli/src/server_subcommands.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ use std::{net::Ipv4Addr, str::FromStr, thread, time::Duration};
22

33
use anyhow::Context;
44
use clap::Subcommand;
5-
use rw3d_net::{connection::WitcherConnection, messages::requests::*};
5+
use rw3d_net::{connection::{WitcherConnection, WitcherPort}, messages::requests::*};
66
use rw3d_net_client::WitcherClient;
77

8-
use crate::{logging::println_log, response_handling::*, CliOptions};
8+
use crate::{logging::println_log, response_handling::*, CliOptions, ConnectionTarget};
99

1010

1111
/// Subcommands that require connection to game's socket and sending messages to it
@@ -52,11 +52,17 @@ pub(crate) fn handle_server_subcommand( cmd: ServerSubcommands, options: CliOpti
5252

5353
const CONNECT_TIMEOUT_MILLIS: u64 = 5000;
5454

55+
let port = if options.target == ConnectionTarget::Game {
56+
WitcherPort::Game
57+
} else {
58+
WitcherPort::Editor
59+
};
60+
5561
println_log("Connecting to the game...");
5662
let mut connection =
57-
WitcherConnection::connect_timeout(ip.into(), Duration::from_millis(CONNECT_TIMEOUT_MILLIS))
58-
.context(format!("Failed to connect to the game on address {}.\n\
59-
Make sure the game is running and that it was launched with following flags: -net -debugscripts.", ip.to_string()))?;
63+
WitcherConnection::connect_timeout(ip.into(), port.clone(), Duration::from_millis(CONNECT_TIMEOUT_MILLIS))
64+
.context(format!("Failed to connect to the game on address {}:{}.\n\
65+
Make sure the game is running and that it was launched with following flags: -net -debugscripts.", ip.to_string(), port.as_number()))?;
6066

6167
connection.set_read_timeout(Duration::from_millis(options.response_timeout)).unwrap();
6268

crates/mock-server/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{collections::HashMap, net::{Ipv4Addr, TcpListener, TcpStream}, sync::{atomic::AtomicBool, Arc}};
22

3-
use rw3d_net::{connection::WitcherConnection, messages::{notifications::*, requests::*, Message, MessageId, MessageIdRegistry}, protocol::{Decode, Encode, WitcherPacket}};
3+
use rw3d_net::{connection::WitcherPort, messages::{notifications::*, requests::*, Message, MessageId, MessageIdRegistry}, protocol::{Decode, Encode, WitcherPacket}};
44

55

66
pub struct MockWitcherServer {
@@ -16,7 +16,7 @@ impl MockWitcherServer {
1616
const READ_TIMEOUT_MILLIS: u64 = 100;
1717

1818
pub fn new() -> anyhow::Result<Arc<Self>> {
19-
let listener = TcpListener::bind((Ipv4Addr::LOCALHOST, WitcherConnection::GAME_PORT))?;
19+
let listener = TcpListener::bind((Ipv4Addr::LOCALHOST, WitcherPort::Game.as_number()))?;
2020
listener.set_nonblocking(true).unwrap();
2121

2222
let mut id_registry = MessageIdRegistry::new();
@@ -52,7 +52,7 @@ impl MockWitcherServer {
5252

5353

5454
pub fn listen(self: Arc<Self>, cancel_token: Arc<AtomicBool>) {
55-
println!("Server listening on port {}", WitcherConnection::GAME_PORT);
55+
println!("Server listening on port {}", WitcherPort::Game.as_number());
5656

5757
loop {
5858
if cancel_token.load(std::sync::atomic::Ordering::Relaxed) {

crates/net-client/tests/integration.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{net::Ipv4Addr, sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Arc}, time::Duration};
22

33
use rw3d_mock_server::MockWitcherServer;
4-
use rw3d_net::{connection::WitcherConnection, messages::{notifications::*, requests::*}};
4+
use rw3d_net::{connection::{WitcherConnection, WitcherPort}, messages::{notifications::*, requests::*}};
55
use rw3d_net_client::WitcherClient;
66

77

@@ -19,7 +19,7 @@ fn integration_test() -> anyhow::Result<()> {
1919
// wait for the server to set up
2020
std::thread::sleep(std::time::Duration::from_millis(100));
2121

22-
let conn = WitcherConnection::connect_timeout(Ipv4Addr::LOCALHOST.into(), Duration::from_secs(1))?;
22+
let conn = WitcherConnection::connect_timeout(Ipv4Addr::LOCALHOST.into(), WitcherPort::Game, Duration::from_secs(1))?;
2323
let client = WitcherClient::new(conn);
2424
client.start()?;
2525

crates/net/src/connection.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ pub struct WitcherConnection {
1111
}
1212

1313
impl WitcherConnection {
14-
pub const GAME_PORT: u16 = 37001;
1514
/// A read timeout is necessary to be able to shut down the connection
1615
/// Without it it would block infinitely until it would receive data or the connection was severed
1716
pub const DEFAULT_READ_TIMEOUT_MILLIS: u64 = 2000;
1817

19-
pub fn connect(ip: IpAddr) -> anyhow::Result<Self> {
20-
let addr = SocketAddr::new(ip, Self::GAME_PORT);
18+
19+
pub fn connect(ip: IpAddr, port: WitcherPort) -> anyhow::Result<Self> {
20+
let addr = SocketAddr::new(ip, port.as_number());
2121
let stream = TcpStream::connect(addr)?;
2222
stream.set_read_timeout(Some(std::time::Duration::from_millis(Self::DEFAULT_READ_TIMEOUT_MILLIS)))?;
2323

@@ -26,8 +26,8 @@ impl WitcherConnection {
2626
})
2727
}
2828

29-
pub fn connect_timeout(ip: IpAddr, timeout: Duration) -> anyhow::Result<Self> {
30-
let addr = SocketAddr::new(ip, Self::GAME_PORT);
29+
pub fn connect_timeout(ip: IpAddr, port: WitcherPort, timeout: Duration) -> anyhow::Result<Self> {
30+
let addr = SocketAddr::new(ip, port.as_number());
3131
let stream = TcpStream::connect_timeout(&addr, timeout)?;
3232
stream.set_read_timeout(Some(std::time::Duration::from_millis(Self::DEFAULT_READ_TIMEOUT_MILLIS)))?;
3333

@@ -90,4 +90,28 @@ impl WitcherConnection {
9090
self.stream.shutdown(std::net::Shutdown::Both)?;
9191
Ok(())
9292
}
93+
}
94+
95+
96+
/// Describes Witcher 3's connection port
97+
#[derive(Debug, Clone, PartialEq, Eq, Default)]
98+
pub enum WitcherPort {
99+
/// Connect to the game running on its own
100+
#[default]
101+
Game,
102+
/// Connect to the game running through REDKit
103+
Editor,
104+
/// Connect on a custom port
105+
Custom(u16)
106+
}
107+
108+
impl WitcherPort {
109+
#[inline]
110+
pub fn as_number(&self) -> u16 {
111+
match self {
112+
WitcherPort::Editor => 37000,
113+
WitcherPort::Game => 37001,
114+
WitcherPort::Custom(p) => *p,
115+
}
116+
}
93117
}

0 commit comments

Comments
 (0)