Skip to content

Commit 0dd3cef

Browse files
authored
Merge branch 'master' into feat/new-presence
2 parents 625bdd0 + cbde5f0 commit 0dd3cef

30 files changed

Lines changed: 657 additions & 178 deletions

.github/workflows/build-ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: Maxima Build
22

3-
on: [push, pull_request]
3+
on: [push]
44

55
concurrency:
66
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,3 @@ strip = true
1616
[patch.crates-io]
1717
flate2 = { git = 'https://github.com/ArmchairDevelopers/flate2-rs.git' }
1818
async-compression = { git = 'https://github.com/ArmchairDevelopers/async-compression.git' }
19-
dll-syringe = { git = "https://github.com/fry/dll-syringe", rev = "0a8b18e" }

README.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
![Logo](images/1500x500.jpg)
44

55
> [!WARNING]
6-
> Maxima is in beta. Parts of it may not be fully stable, and we're actively fixing bugs and adding features. Please create an [issue](https://github.com/ArmchairDevelopers/Maxima/issues) if you notice strange behavior.
6+
> Maxima is pre-pre-pre-alpha-quality software, and is being made open source **prematurely** for [KYBER](https://github.com/ArmchairDevelopers/Kyber), which depends on it. We cannot yet provide any support for attempting to use it standalone, although bug-fixes and [contributions](CONTRIBUTING.md) are welcome.
77
8-
Maxima is an open-source replacement for the EA Desktop/Origin game launcher, running natively on Linux and Windows, with MacOS support in progress.
8+
Maxima is an open-source replacement for the EA Desktop/Origin game launcher, running natively on Linux and Windows, with macOS support in progress.
99

10-
Maxima itself is a library (`maxima-lib`), with povided CLI (`maxima-cli`), TUI (`maxima-tui`), and GUI (`maxima-ui`) frontends. Other launchers compatible with Maxima's license may implement it as a backend. It's used by our sister project, [KYBER](https://uplink.kyber.gg/news/features-overview).
10+
Maxima itself is a library (`maxima-lib`), with provided CLI (`maxima-cli`), TUI (`maxima-tui`), and GUI (`maxima-ui`) frontends. Other launchers compatible with Maxima's license may implement it as a backend. It's used by our sister project, [KYBER](https://uplink.kyber.gg/news/features-overview).
1111

1212
![UI](images/UI.png)
1313

@@ -26,13 +26,13 @@ Maxima itself is a library (`maxima-lib`), with povided CLI (`maxima-cli`), TUI
2626
- `proton-ge` is automatically installed together with [umu](https://github.com/Open-Wine-Components/umu-launcher).
2727

2828
**In-Dev:**
29-
- MacOS support
29+
- macOS support
3030
- Support for launching Maxima through Epic/Steam
3131

3232
**Planned:**
3333
- Library documentation/examples
3434
- Support for installing DLCs
35-
- Full EA Desktop interopability. Games installed with EA Desktop already appear on Maxima, but to take it a step further we'd like the ability to, for example, start a download on EA Desktop and continue it on Maxima.
35+
- Full EA Desktop interoperability. Games installed with EA Desktop already appear on Maxima, but to take it a step further we'd like the ability to, for example, start a download on EA Desktop and continue it on Maxima.
3636
- Cleaner/Stabler downloader implementation
3737
- Progressive/Selective installs
3838
- Some games are able to start without being fully installed, and some games contain language-specific files.
@@ -57,7 +57,12 @@ It's the farthest you can get from the Origin.
5757
## Contributing
5858
See [CONTRIBUTING.md](./CONTRIBUTING.md)
5959

60+
## Honorable mentions
61+
- [Sean Kahler](https://github.com/battledash)
62+
- Former Core maintainer
63+
- Creator of Maxima
64+
6065
## Maintainers:
61-
- [Sean Kahler](https://github.com/battledash) (Core)
6266
- [Nick Whelan](https://github.com/headassbtw) (UI)
6367
- [Paweł Lidwin](https://github.com/imLinguin) (Core)
68+

maxima-cli/src/main.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use maxima::{
3131
},
3232
clients::JUNO_PC_CLIENT_ID,
3333
cloudsync::CloudSyncLockMode,
34-
launch::{self, LaunchMode},
34+
launch::{self, LaunchMode, LaunchOptions},
3535
library::OwnedTitle,
3636
manifest::{self, MANIFEST_RELATIVE_PATH},
3737
service_layer::{
@@ -829,12 +829,17 @@ async fn start_game(
829829
}
830830
}
831831

832+
let launch_options = LaunchOptions {
833+
path_override: game_path_override,
834+
arguments: game_args,
835+
cloud_saves: true,
836+
};
837+
832838
if login.is_none() {
833839
launch::start_game(
834840
maxima_arc.clone(),
835841
LaunchMode::Online(offer_id.to_owned()),
836-
game_path_override,
837-
game_args,
842+
launch_options,
838843
)
839844
.await?;
840845
} else if let Some(captures) = MANUAL_LOGIN_PATTERN.captures(&login.unwrap()) {
@@ -844,8 +849,7 @@ async fn start_game(
844849
launch::start_game(
845850
maxima_arc.clone(),
846851
LaunchMode::OnlineOffline(offer_id.to_owned(), persona.to_owned(), password.to_owned()),
847-
game_path_override,
848-
game_args,
852+
launch_options,
849853
)
850854
.await?;
851855
}

maxima-lib/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ hex = "0.4.3"
2929
lazy_static = "1.4.0"
3030
reqwest = { version = "0.11.18", features = ["stream", "rustls-tls", "gzip", "json"], default-features = false }
3131
base64 = "0.21.2"
32+
base62 = "2.2.0"
3233
log = "0.4.19"
3334
enable-ansi-support = "0.2.1"
3435
chrono = "0.4.26"
@@ -41,7 +42,7 @@ sysinfo = "0.29.7"
4142
strum_macros = "0.25.2"
4243
sha2-const = "0.1.2"
4344
tar = "0.4"
44-
flate2 = { version = "1.0.28", default-features = false, features = ["zlib-default"] }
45+
flate2 = { version = "=1.0.28", default-features = false, features = ["zlib-default"] }
4546
xz2 = "0.1.7"
4647
zstd = "0.13.0"
4748
toml = "0.8.8"
@@ -98,7 +99,6 @@ winreg = "0.51.0"
9899
windows-service = "0.6.0"
99100
is_elevated = "0.1.2"
100101
widestring = "1.0.2"
101-
dll-syringe = "0.15.2"
102102
wmi = "0.13.1"
103103

104104
[target.'cfg(target_os = "macos")'.dependencies]

maxima-lib/src/core/auth/context.rs

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::borrow::Cow;
2+
13
use crate::core::{
24
auth::{hardware::HardwareHashError, pc_sign::PCSign, storage::AuthError},
35
clients::JUNO_PC_CLIENT_ID,
@@ -15,6 +17,8 @@ pub struct AuthContext<'a> {
1517
code: Option<String>,
1618
scopes: Vec<String>,
1719
access_token: Option<String>,
20+
token_format: Option<String>,
21+
expires_in: Option<i64>,
1822
pc_sign: PCSign<'a>,
1923
}
2024

@@ -30,20 +34,19 @@ impl AuthContext<'_> {
3034
code: None,
3135
scopes: Vec::new(),
3236
access_token: None,
37+
token_format: None,
38+
expires_in: None,
3339
pc_sign: signature,
3440
})
3541
}
3642

37-
/// Generates 32 byte long buffer used for code_verifier
3843
fn generate_code_verifier() -> String {
3944
let rand_bytes: [u8; 32] = random();
40-
4145
URL_SAFE_NO_PAD.encode(&rand_bytes)
4246
}
4347

4448
fn generate_challenge(code_verifier: &String) -> String {
4549
let hash = Sha256::new().update(code_verifier.as_bytes()).finalize();
46-
4750
URL_SAFE_NO_PAD.encode(hash)
4851
}
4952

@@ -57,16 +60,12 @@ impl AuthContext<'_> {
5760
Ok(payload.to_string() + "." + URL_SAFE_NO_PAD.encode(value).as_ref())
5861
}
5962

60-
/// Returns String representation of code_verifier
6163
pub fn code_verifier(&self) -> &str {
6264
&self.code_verifier
6365
}
6466

6567
pub fn code(&self) -> Option<&str> {
66-
match &self.code {
67-
Some(code) => Some(&code),
68-
None => None,
69-
}
68+
self.code.as_deref()
7069
}
7170

7271
pub fn add_scope(&mut self, scope: &str) {
@@ -78,16 +77,29 @@ impl AuthContext<'_> {
7877
}
7978

8079
pub fn access_token(&self) -> Option<&str> {
81-
match &self.access_token {
82-
Some(access_token) => Some(&access_token),
83-
None => None,
84-
}
80+
self.access_token.as_deref()
8581
}
8682

8783
pub fn set_access_token(&mut self, token: &str) {
8884
self.access_token = Some(token.to_owned())
8985
}
9086

87+
pub fn token_format(&self) -> Option<&str> {
88+
self.token_format.as_deref()
89+
}
90+
91+
pub fn set_token_format(&mut self, token_format: &str) {
92+
self.token_format = Some(token_format.to_owned());
93+
}
94+
95+
pub fn expires_in(&self) -> Option<i64> {
96+
self.expires_in
97+
}
98+
99+
pub fn set_expires_in(&mut self, expires_in: i64) {
100+
self.expires_in = Some(expires_in);
101+
}
102+
91103
pub fn nucleus_auth_url(
92104
&self,
93105
client_id: &str,
@@ -97,26 +109,34 @@ impl AuthContext<'_> {
97109
let nonce = random::<i32>().to_string();
98110

99111
let mut query = vec![
100-
("client_id", client_id),
101-
("sbiod_enabled", "false"),
102-
("response_type", response_type),
103-
("locale", "en_US"),
104-
("pc_sign", &signature),
105-
("nonce", &nonce),
112+
("client_id", Cow::Borrowed(client_id)),
113+
("sbiod_enabled", Cow::Borrowed("false")),
114+
("response_type", Cow::Borrowed(response_type)),
115+
("locale", Cow::Borrowed("en_US")),
116+
("pc_sign", Cow::Borrowed(&signature)),
117+
("nonce", Cow::Borrowed(&nonce)),
106118
];
107119

108120
let scopes = self.scopes.join(" ");
109121
if !scopes.is_empty() {
110-
query.push(("scope", &scopes));
122+
query.push(("scope", Cow::Owned(scopes)));
111123
}
112124

113125
if client_id == JUNO_PC_CLIENT_ID {
114-
query.push(("code_challenge_method", "S256"));
115-
query.push(("code_challenge", &self.code_challenge));
126+
query.push(("code_challenge_method", Cow::Borrowed("S256")));
127+
query.push(("code_challenge", Cow::Borrowed(&self.code_challenge)));
116128
}
117129

118130
if let Some(access_token) = &self.access_token {
119-
query.push(("access_token", access_token));
131+
query.push(("access_token", Cow::Borrowed(access_token)));
132+
}
133+
134+
if let Some(token_format) = &self.token_format {
135+
query.push(("token_format", Cow::Borrowed(token_format)));
136+
}
137+
138+
if let Some(expires_in) = self.expires_in {
139+
query.push(("expires_in", Cow::Owned(expires_in.to_string())));
120140
}
121141

122142
let url = reqwest::Url::parse_with_params(API_NUCLEUS_AUTH, query)?;

maxima-lib/src/core/auth/hardware.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ impl HardwareInfo {
255255

256256
use crate::util::system_profiler_utils::SPDisplaysDataType;
257257

258-
let smbios_data = table_load_from_device()?;
258+
let smbios_data = table_load_from_device().unwrap();
259259
let bios_data = smbios_data.first::<SMBiosSystemInformation>();
260260
let board_data = smbios_data.first::<SMBiosBaseboardInformation>();
261261

@@ -282,7 +282,7 @@ impl HardwareInfo {
282282
let mut gpu_pnp_id: Option<String> = None;
283283
let output = Command::new("system_profiler")
284284
.args(["SPDisplaysDataType", "-json"])
285-
.output()?;
285+
.output().unwrap();
286286
if output.status.success() {
287287
let json = String::from_utf8_lossy(&output.stdout);
288288
let result: SPDisplaysDataType = serde_json::from_str(&json).unwrap();
@@ -298,7 +298,7 @@ impl HardwareInfo {
298298
}
299299

300300
let mut disk_sn = String::from("None");
301-
let output = Command::new("diskutil").args(["info", "/"]).output()?;
301+
let output = Command::new("diskutil").args(["info", "/"]).output().unwrap();
302302
// Check if the command was successful
303303
if output.status.success() {
304304
// Convert the output bytes to a UTF-8 string
@@ -327,6 +327,7 @@ impl HardwareInfo {
327327
volume_sn: String::from("43000000"),
328328
mac,
329329
cpu_details,
330+
hostname,
330331
}
331332
}
332333

maxima-lib/src/core/background_service_win.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use dll_syringe::{process::OwnedProcess, Syringe};
21
use log::debug;
32
use reqwest::StatusCode;
43
use serde::{Deserialize, Serialize};
54

65
use crate::core::error::BackgroundServiceClientError;
6+
use crate::util::dll_injector::DllInjector;
77
use crate::util::native::NativeError;
88
use crate::util::registry::{set_up_registry, RegistryError};
99
use is_elevated::is_elevated;
@@ -23,9 +23,8 @@ pub async fn request_library_injection(
2323
debug!("Injecting {}", path);
2424

2525
if is_elevated() {
26-
let process = OwnedProcess::from_pid(pid)?;
27-
let syringe = Syringe::for_process(process);
28-
syringe.inject(path)?;
26+
let injector = DllInjector::new(pid);
27+
injector.inject(path)?;
2928
return Ok(());
3029
}
3130

0 commit comments

Comments
 (0)