From 014300789ec06b6c57f9619f762430ac4602a59e Mon Sep 17 00:00:00 2001 From: Fireblade <72758695+Firebladedoge229@users.noreply.github.com> Date: Wed, 22 May 2024 20:11:19 -0400 Subject: [PATCH] Add Features --- robloxstudiomanager.py | 186 +++++++++++++++++++++++++++++++++-------- 1 file changed, 153 insertions(+), 33 deletions(-) diff --git a/robloxstudiomanager.py b/robloxstudiomanager.py index 89df23f..4ef1e14 100644 --- a/robloxstudiomanager.py +++ b/robloxstudiomanager.py @@ -2,9 +2,11 @@ import re import sys import json +import time import psutil import sv_ttk import requests +import threading import tkinter as tk from tkinter import ttk, messagebox from tkinter import messagebox @@ -14,7 +16,75 @@ else: application_path = os.path.dirname(os.path.abspath(__file__)) +global selected_version +selected_version = None + +optimizer = "https://raw.githubusercontent.com/rbxflags/Flags/main/ClientAppSettings.json" + +versions_dir = os.path.join(os.environ['LOCALAPPDATA'], 'Roblox', 'Versions') + +max_files_count = 0 + +for version in os.listdir(versions_dir): + version_dir = os.path.join(versions_dir, version) + + exe_path = os.path.join(version_dir, 'RobloxStudioBeta.exe') + if os.path.exists(exe_path): + num_files = len([name for name in os.listdir(version_dir)]) + + if num_files > max_files_count: + max_files_count = num_files + selected_version = version_dir + +def is_modded(): + if os.path.exists(os.path.join(selected_version, 'ClientSettings')): + return "Yes" + else: + return "No" + +def check_internet(): + try: + requests.head("http://www.google.com", timeout=5) + return True + except requests.ConnectionError: + return False + +def find_version_line(version, lines): + for line in lines.splitlines(): + if version in line: + return line + return None + +def reset_fflags(): + result = messagebox.askyesno("Roblox Studio Manager", "Are you sure you want to reset your FFlags?") + if result: + app_settings_path = os.path.join(selected_version, 'ClientSettings', 'ClientAppSettings.json') + if os.path.exists(os.path.join(selected_version, 'ClientSettings')): + open(app_settings_path, "w").close() + open(app_settings_path, "w+").write("{}") + +def installation_folder(): + os.system(f'explorer "{selected_version}') + +def launch_studio_async(): + os.system(f"{selected_version}\RobloxStudioBeta.exe") + +def update_studio_async(): + os.system(f"{selected_version}\RobloxStudioInstaller.exe") + def update_settings(): + t = threading.Thread(target=update_settings_async) + t.start() + +def launch_studio(): + t = threading.Thread(target=launch_studio_async) + t.start() + +def update_studio(): + t = threading.Thread(target=update_studio_async) + t.start() + +def update_settings_async(): studio_id = studio_running() if studio_id: @@ -23,12 +93,15 @@ def update_settings(): psutil.Process(studio_id).kill() psutil.Process(studio_id).wait() + start_time = time.time() + optimize_roblox = optimize_roblox_var.get() menu_type = menu_type_var.get() topbar_type = topbar_type_var.get() msaa_level = msaa_level_var.get() graphics_type = graphics_type_var.get() max_fps = max_fps_var.get() + font_size = font_size_var.get() log_requests = log_requests_var.get() enable_proxy = enable_proxy_var.get() enable_internal = enable_internal_var.get() @@ -41,11 +114,13 @@ def update_settings(): visual_verified = visual_verified_var.get() old_font = old_font_var.get() classic_error = classic_error_var.get() - framerate_cap = framerate_cap_var.get() + disable_updating = disable_updating_var.get() + extra_plugins = extra_plugins_var.get() flags = { "FFlagDebugGraphicsPreferD3D11": "true", # directx 11 usage - "DFIntTaskSchedulerTargetFps": int(max_fps) # max fps + "DFIntTaskSchedulerTargetFps": int(max_fps), # max fps + "FIntFontSizePadding": int(font_size) # font size } internal_signature = b"\x80\xBF\x78\x01\x00\x00\x00\x74\x05\xE8" @@ -77,6 +152,7 @@ def update_settings(): flags["FFlagEnableInGameMenuChrome"] = "false" # version 4 menu elif topbar_type == "New": flags["FFlagEnableInGameMenuChrome"] = "true" # version 4 menu + flags["FFlagEnableChromePinnedChat"] = "false" # disable chat if log_requests: flags["DFLogHttpTraceLight"] = 12 @@ -151,24 +227,12 @@ def update_settings(): if classic_error: flags["FFlagErrorPromptResizesHeight"] = "false" - if framerate_cap: - flags["FFlagGameBasicSettingsFramerateCap5"] = "true" - - versions_dir = os.path.join(os.environ['LOCALAPPDATA'], 'Roblox', 'Versions') - - max_files_count = 0 - selected_version = None - - for version in os.listdir(versions_dir): - version_dir = os.path.join(versions_dir, version) - - exe_path = os.path.join(version_dir, 'RobloxStudioBeta.exe') - if os.path.exists(exe_path): - num_files = len([name for name in os.listdir(version_dir)]) - - if num_files > max_files_count: - max_files_count = num_files - selected_version = version_dir + if extra_plugins: + flags["FFlagEnableRibbonPlugin"] = "true" + flags["FFlagDebugAvatarInternalToolsPlugin"] = "true" + flags["NestedPackagePublisherPlugin"] = "true" + flags["DebugEnableBootcampPlugin"] = "true" + flags["RetireAudioDiscoveryPlugin"] = "false" if selected_version is not None: app_settings_path = os.path.join(selected_version, 'ClientSettings', 'ClientAppSettings.json') @@ -183,12 +247,13 @@ def update_settings(): app_settings = json.load(f) if optimize_roblox: request = requests.get( - "https://web.archive.org/web/20231022202217if_/https://raw.githubusercontent.com/Kaiddd/Roblox-Client-Optimizer/8b892138f869092d545434e2769518dab399f89b/ClientAppSettings.json").json() + optimizer).json() for k, v in request.items(): - v = re.sub(r'https://web\.archive\.org/web/\d+/', "", v) - app_settings[k] = v + if k != "DFIntTaskSchedulerTargetFPS": + app_settings[k] = v for k, v in flags.items(): - app_settings[k] = v + if k != "DFIntTaskSchedulerTargetFPS": + app_settings[k] = v f.seek(0) json.dump(app_settings, f, indent=4) f.truncate() @@ -210,8 +275,33 @@ def update_settings(): f.seek(index) f.write(internal_signature) - else: - print("No version with RobloxStudioBeta.exe found.") + result = find_version_line(os.path.basename(selected_version), requests.get("https://setup.rbxcdn.com/DeployHistory.txt").text) + result = re.search(r'git hash:\s*(\d+\.\d+\.\d+\.\d+)', result).group().replace("git hash: ", "") + patch = re.sub(r'\d', '9', result) + result = bytes.fromhex("".join(format(ord(char), '02X') for char in result)) + patch = bytes.fromhex("".join(format(ord(char), '02X') for char in patch)) + + if disable_updating: + print(str(result), str(patch)) + exe_path = os.path.join(selected_version, 'RobloxStudioBeta.exe') + with open(exe_path, 'r+b') as f: + content = f.read() + index = content.find(result) + if index != -1: + f.seek(index) + f.write(patch) + elif disable_updating == False: + exe_path = os.path.join(selected_version, 'RobloxStudioBeta.exe') + with open(exe_path, 'r+b') as f: + content = f.read() + index = content.find(patch) + if index != -1: + f.seek(index) + f.write(result) + + end_time = time.time() + + result = messagebox.showinfo("Roblox Studio Manager", f"Successfully patched in {str(round(end_time - start_time, 2))}ms.") def studio_running(): for proc in psutil.process_iter(): @@ -220,7 +310,7 @@ def studio_running(): return False root = tk.Tk() -root.title("Roblox Settings Manager") +root.title("Roblox Studio Manager") optimize_roblox_var = tk.BooleanVar() menu_type_var = tk.StringVar(value="Version 4") @@ -228,9 +318,9 @@ def studio_running(): msaa_level_var = tk.StringVar(value="4x") graphics_type_var = tk.StringVar(value="21") max_fps_var = tk.StringVar(value="9999") +font_size_var = tk.StringVar(value="1") log_requests_var = tk.BooleanVar() enable_proxy_var = tk.BooleanVar() -enable_internal_var = tk.BooleanVar() show_flags_var = tk.BooleanVar() log_all_var = tk.BooleanVar() code_assist_var = tk.BooleanVar() @@ -240,9 +330,11 @@ def studio_running(): visual_verified_var = tk.BooleanVar(value=False) old_font_var = tk.BooleanVar(value=True) classic_error_var = tk.BooleanVar(value=True) -framerate_cap_var = tk.BooleanVar() +disable_updating_var = tk.BooleanVar() +enable_internal_var = tk.BooleanVar() +extra_plugins_var = tk.BooleanVar() -ttk.Label(root, text="Roblox Settings Manager", font=("Segoe UI", 16)).grid(row=0, column=0, columnspan=4, pady=10) +ttk.Label(root, text="Roblox Studio Manager", font=("Segoe UI", 16)).grid(row=0, column=0, columnspan=4, pady=10) ttk.Checkbutton(root, text="Optimize Roblox", variable=optimize_roblox_var).grid(row=1, column=0, sticky=tk.W, padx=10) ttk.Label(root, text="Menu Type:").grid(row=2, column=0, sticky=tk.W, padx=10) @@ -268,6 +360,15 @@ def studio_running(): ttk.Label(root, text="Max FPS:").grid(row=6, column=0, sticky=tk.W, padx=10) ttk.Entry(root, textvariable=max_fps_var).grid(row=6, column=1, sticky="ew") +ttk.Label(root, text="Font Size:").grid(row=7, column=0, sticky=tk.W, padx=10) +ttk.Entry(root, textvariable=font_size_var).grid(row=7, column=1, sticky="ew") + +ttk.Label(root, text="Version:").grid(row=8, column=0, sticky=tk.W, padx=10) +ttk.Label(root, text=os.path.basename(selected_version)).grid(row=8, column=1, sticky=tk.W, padx=10) + +ttk.Label(root, text="Modded:").grid(row=9, column=0, sticky=tk.W, padx=10) +ttk.Label(root, text=is_modded()).grid(row=9, column=1, sticky=tk.W, padx=10) + ttk.Checkbutton(root, text="Log Requests", variable=log_requests_var).grid(row=1, column=2, sticky=tk.W, padx=10, pady=3) ttk.Checkbutton(root, text="Enable Proxy", variable=enable_proxy_var).grid(row=2, column=2, sticky=tk.W, padx=10, pady=3) ttk.Checkbutton(root, text="Show Flags", variable=show_flags_var).grid(row=3, column=2, sticky=tk.W, padx=10, pady=3) @@ -279,10 +380,29 @@ def studio_running(): ttk.Checkbutton(root, text="Verified Badge", variable=visual_verified_var).grid(row=9, column=2, sticky=tk.W, padx=10, pady=3) ttk.Checkbutton(root, text="Classic Font", variable=old_font_var).grid(row=1, column=3, sticky=tk.W, padx=10, pady=3) ttk.Checkbutton(root, text="Classic Error", variable=classic_error_var).grid(row=2, column=3, sticky=tk.W, padx=10, pady=3) -ttk.Checkbutton(root, text="Framerate Settings", variable=framerate_cap_var).grid(row=3, column=3, sticky=tk.W, padx=10, pady=3) -ttk.Checkbutton(root, text="Enable Internal", variable=enable_internal_var).grid(row=4, column=3, sticky=tk.W, padx=10, pady=3) +ttk.Checkbutton(root, text="Extra Plugins", variable=extra_plugins_var).grid(row=3, column=3, sticky=tk.W, padx=10, pady=3) +disable_updates_cb = ttk.Checkbutton(root, text="Disable Updates", variable=disable_updating_var, state = "disabled") +disable_updates_cb.grid(row=4, column=3, sticky=tk.W, padx=10, pady=3) +ttk.Checkbutton(root, text="Enable Internal", variable=enable_internal_var).grid(row=5, column=3, sticky=tk.W, padx=10, pady=3) + +button_frame_top = ttk.Frame(root) +button_frame_top.grid(row=10, column=1, columnspan=2, pady=(0, 1), sticky="n") +button_frame_bottom = ttk.Frame(root) +button_frame_bottom.grid(row=11, column=1, columnspan=2, sticky="n") + +ttk.Button(button_frame_top, text="Apply Settings", command=update_settings).grid(row=10, column=0, pady=(20, 0)) +ttk.Button(button_frame_top, text="Reset Configuration", command=reset_fflags).grid(row=10, column=1, pady=(20, 0), padx=(6, 0)) +ttk.Button(button_frame_top, text="Installation Folder", command=installation_folder).grid(row=10, column=2, pady=(20, 0), padx=(6, 0)) +ttk.Button(button_frame_bottom, text="Launch Studio", command=launch_studio).grid(row=11, column=0, pady=(6, 20)) +ttk.Button(button_frame_bottom, text="Update Studio", command=update_studio).grid(row=11, column=1, pady=(6, 20), padx=(6, 0)) + +label = tk.Label(root, font=("Segoe UI", 12), text="Fireblade", padx=2, pady = 2) + +label.place(relx=1.0, rely=1.0, anchor='se') -ttk.Button(root, text="Apply Settings", command=update_settings).grid(row=10, column=0, columnspan=4, pady=20) +if not check_internet(): + optimize_roblox_cb.configure(state = "disabled") + disable_updates_cb.configure(state = "disabled") sv_ttk.set_theme("dark") root.resizable(False, False)