This commit is contained in:
parent
8740c41a63
commit
fd3863c0d4
90
Cargo.lock
generated
90
Cargo.lock
generated
@ -1,7 +1,95 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "alt_enter_fix"
|
name = "alt_enter_fix"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.94"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.219"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.219"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.140"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"memchr",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||||
|
@ -7,3 +7,6 @@ edition = "2021"
|
|||||||
|
|
||||||
[target.x86_64-pc-windows-gnu]
|
[target.x86_64-pc-windows-gnu]
|
||||||
linker = "x86_64-w64-mingw32-gcc"
|
linker = "x86_64-w64-mingw32-gcc"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde_json = "1.0.140"
|
||||||
|
202
src/main.rs
202
src/main.rs
@ -1,60 +1,150 @@
|
|||||||
use std::{env, fs, io::{self, stdin, Read, Write}, path::Path};
|
use serde_json::{json, Value};
|
||||||
fn main() {
|
use std::{env, fs, io::{self, stdin, Read, Write}, path::{Path, PathBuf}};
|
||||||
let mut rblxpath = String::new();
|
|
||||||
if let Some(lad) = env::var("LOCALAPPDATA").ok() {
|
const UNLIMITED_FPS_CAP_NUM: i32 = i32::max_value();
|
||||||
let temprbx_lad = format!("{}\\Roblox", lad);
|
|
||||||
if Path::new(&temprbx_lad).is_dir() {
|
fn main() -> io::Result<()> {
|
||||||
rblxpath = temprbx_lad;
|
let roblox_path = find_roblox_path().ok_or_else(|| {
|
||||||
}
|
|
||||||
} else if let Some(pfx86) = env::var("ProgramFiles(x86)").ok() {
|
|
||||||
let temprbx_pfx86 = format!("{}\\Roblox", pfx86);
|
|
||||||
if Path::new(&temprbx_pfx86).is_dir() {
|
|
||||||
rblxpath = temprbx_pfx86;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if rblxpath != "" {
|
|
||||||
println!("Found path: {}", rblxpath);
|
|
||||||
} else {
|
|
||||||
println!("Roblox not found (Die)");
|
println!("Roblox not found (Die)");
|
||||||
return;
|
io::Error::new(io::ErrorKind::NotFound, "Roblox installation not found")
|
||||||
}
|
})?;
|
||||||
|
|
||||||
|
println!("Found path: {}", roblox_path.display());
|
||||||
|
|
||||||
println!("What FPS would you like to cap the fps to? (0 for no cap at all)");
|
println!("What FPS would you like to cap the fps to? (0 for no cap at all)");
|
||||||
let _ = io::stdout().flush();
|
io::stdout().flush()?;
|
||||||
let mut input = String::new();
|
|
||||||
stdin().read_line(&mut input).expect("invalid input, try again");
|
let fps = read_fps_input()?;
|
||||||
if let Some('\n')=input.chars().next_back() {
|
let desired_fps = if fps == 0 { UNLIMITED_FPS_CAP_NUM } else { fps };
|
||||||
input.pop();
|
|
||||||
}
|
println!("FPS cap will be set to {desired_fps}");
|
||||||
if let Some('\r')=input.chars().next_back() {
|
|
||||||
input.pop();
|
let required_settings = json!({
|
||||||
}
|
// Restore original 'alt-enter' behaviour
|
||||||
let fps = input.parse::<i32>().unwrap();
|
"FFlagHandleAltEnterFullscreenManually": "False",
|
||||||
let desired_fps = match fps {
|
|
||||||
0 => 5588562,
|
// Disable Roblox's built-in 240 fps hard-coded cap and replace with custom cap
|
||||||
_ => fps
|
"DFIntTaskSchedulerTargetFps": desired_fps,
|
||||||
};
|
"FFlagGameBasicSettingsFramerateCap5": "False",
|
||||||
println!("fps cap will be set to {desired_fps}");
|
"FFlagTaskSchedulerLimitTargetFpsTo2402": "False",
|
||||||
let just_make_this_work = format!("{{\"FFlagHandleAltEnterFullscreenManually\":\"False\",\"DFIntTaskSchedulerTargetFps\":{desired_fps},\"FFlagEnableInGameMenuChromeABTest3\":\"False\",\"FFlagGameBasicSettingsFramerateCap5\":\"False\",\"FFlagTaskSchedulerLimitTargetFpsTo2402\":\"False\"}}");
|
|
||||||
let fflag_contents = just_make_this_work.as_str();
|
// Ensure Direct3D11 is the rendering API for optimal performance
|
||||||
let versions = format!("{}\\Versions\\", rblxpath);
|
"FFlagDebugGraphicsDisableDirect3D11": "False",
|
||||||
for folder in fs::read_dir(versions).unwrap() {
|
"FFlagDebugGraphicsPreferD3D11": "True",
|
||||||
let cur_folder = folder.unwrap().path().display().to_string();
|
|
||||||
if cur_folder.to_lowercase().contains("version") {
|
// Disable telemetry related FFlags
|
||||||
let executable = format!("{}\\RobloxPlayerBeta.exe", cur_folder);
|
"FFlagDebugDisableTelemetryEphemeralCounter": "True",
|
||||||
if Path::new(&executable).is_file() {
|
"FFlagDebugDisableTelemetryEphemeralStat": "True",
|
||||||
let cs_folder = format!("{}\\ClientSettings", cur_folder);
|
"FFlagDebugDisableTelemetryEventIngest": "True",
|
||||||
if !Path::new(&cs_folder).is_dir() {
|
"FFlagDebugDisableTelemetryPoint": "True",
|
||||||
fs::create_dir(&cs_folder).ok();
|
"FFlagDebugDisableTelemetryV2Counter": "True",
|
||||||
println!("Created ClientSettings folder in {}", cur_folder);
|
"FFlagDebugDisableTelemetryV2Event": "True",
|
||||||
} else {
|
"FFlagDebugDisableTelemetryV2Stat": "True"
|
||||||
println!("ClientSettings folder already exists in {}", cur_folder);
|
});
|
||||||
}
|
|
||||||
let cas_json = format!("{}\\ClientAppSettings.json", cs_folder);
|
update_client_settings(&roblox_path, required_settings)?;
|
||||||
fs::write(cas_json, fflag_contents).ok();
|
|
||||||
println!("Wrote ClientAppSettings.json to {}", cur_folder)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("Press enter to exit");
|
println!("Press enter to exit");
|
||||||
let _ = io::stdin().read(&mut [0u8]).unwrap();
|
let _ = io::stdin().read(&mut [0u8])?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_roblox_path() -> Option<PathBuf> {
|
||||||
|
if let Some(local_app_data) = env::var("LOCALAPPDATA").ok() {
|
||||||
|
let path = PathBuf::from(local_app_data).join("Roblox");
|
||||||
|
if path.is_dir() {
|
||||||
|
return Some(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is here because Roblox installs into Program Files (x86) if you run the installer as administrator (??? lol)
|
||||||
|
if let Some(program_files) = env::var("ProgramFiles(x86)").ok() {
|
||||||
|
let path = PathBuf::from(program_files).join("Roblox");
|
||||||
|
if path.is_dir() {
|
||||||
|
return Some(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_fps_input() -> io::Result<i32> {
|
||||||
|
let mut input = String::new();
|
||||||
|
stdin().read_line(&mut input)?;
|
||||||
|
|
||||||
|
let input = input.trim();
|
||||||
|
|
||||||
|
input.parse::<i32>().map_err(|_| {
|
||||||
|
io::Error::new(io::ErrorKind::InvalidInput, "Invalid FPS value")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_client_settings(roblox_path: &Path, required_settings: Value) -> io::Result<()> {
|
||||||
|
let versions_path = roblox_path.join("Versions");
|
||||||
|
|
||||||
|
for entry in fs::read_dir(versions_path)? {
|
||||||
|
let entry = entry?;
|
||||||
|
let path = entry.path();
|
||||||
|
let path_str = path.to_string_lossy().to_lowercase();
|
||||||
|
|
||||||
|
if path_str.contains("version") {
|
||||||
|
let executable = path.join("RobloxPlayerBeta.exe");
|
||||||
|
|
||||||
|
if executable.is_file() {
|
||||||
|
let client_settings_dir = path.join("ClientSettings");
|
||||||
|
|
||||||
|
if !client_settings_dir.exists() {
|
||||||
|
fs::create_dir(&client_settings_dir)?;
|
||||||
|
println!("Created ClientSettings folder in {}", path.display());
|
||||||
|
} else {
|
||||||
|
println!("ClientSettings folder already exists in {}", path.display());
|
||||||
|
}
|
||||||
|
|
||||||
|
let settings_file = client_settings_dir.join("ClientAppSettings.json");
|
||||||
|
update_settings_file(&settings_file, &required_settings)?;
|
||||||
|
println!("Updated ClientAppSettings.json in {}", path.display());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_settings_file(file_path: &Path, required_settings: &Value) -> io::Result<()> {
|
||||||
|
// Funky code to edit or create the ClientAppSettings.json file (shoutout claude for the help with the object stuff (json sucks))
|
||||||
|
let mut settings = if file_path.exists() {
|
||||||
|
match fs::read_to_string(file_path) {
|
||||||
|
Ok(content) if !content.trim().is_empty() => {
|
||||||
|
match serde_json::from_str::<Value>(&content) {
|
||||||
|
Ok(existing) => existing,
|
||||||
|
Err(e) => {
|
||||||
|
println!("Warning: Could not parse existing settings ({}), creating new file", e);
|
||||||
|
json!({})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => json!({})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
json!({})
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(required_obj) = required_settings.as_object() {
|
||||||
|
if !settings.is_object() {
|
||||||
|
settings = json!({});
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(settings_obj) = settings.as_object_mut() {
|
||||||
|
for (key, value) in required_obj {
|
||||||
|
println!("Adding {}: {}", key, value);
|
||||||
|
settings_obj.insert(key.clone(), value.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let formatted = serde_json::to_string_pretty(&settings)?;
|
||||||
|
fs::write(file_path, formatted)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user