added a bunch of settings, updated progress bar to simulate the download prgoress (not as bad as it sounds)
This commit is contained in:
parent
baa1ee45b1
commit
1c3cdc7cbf
452
boiiiwd.py
452
boiiiwd.py
@ -26,12 +26,14 @@ LATEST_RELEASE_URL = "https://github.com/faroukbmiled/BOIIIWD/releases/latest/do
|
|||||||
UPDATER_FOLDER = "update"
|
UPDATER_FOLDER = "update"
|
||||||
CONFIG_FILE_PATH = "config.ini"
|
CONFIG_FILE_PATH = "config.ini"
|
||||||
|
|
||||||
# fuck it we ball, ill remove these when i finish with eveything (and replace them with none global bools)
|
# fuck it we ball, ill get rid of globals when i finish everything cant be bothered rn
|
||||||
global stopped, steampid, console, clean_on_finish
|
global stopped, steampid, console, clean_on_finish, continuous, estimated_progress
|
||||||
steampid = None
|
steampid = None
|
||||||
stopped = False
|
stopped = False
|
||||||
console = False
|
console = False
|
||||||
clean_on_finish = True
|
clean_on_finish = True
|
||||||
|
continuous = True
|
||||||
|
estimated_progress = True
|
||||||
|
|
||||||
ctk.set_appearance_mode("Dark") # Modes: "System" (standard), "Dark", "Light"
|
ctk.set_appearance_mode("Dark") # Modes: "System" (standard), "Dark", "Light"
|
||||||
ctk.set_default_color_theme("dark-blue") # Themes: "blue" (standard), "green", "dark-blue"
|
ctk.set_default_color_theme("dark-blue") # Themes: "blue" (standard), "green", "dark-blue"
|
||||||
@ -179,39 +181,59 @@ def create_default_config():
|
|||||||
with open(CONFIG_FILE_PATH, "w") as config_file:
|
with open(CONFIG_FILE_PATH, "w") as config_file:
|
||||||
config.write(config_file)
|
config.write(config_file)
|
||||||
|
|
||||||
def run_steamcmd_command(command, self):
|
def run_steamcmd_command(command, self, map_folder):
|
||||||
|
global steampid, stopped
|
||||||
steamcmd_path = get_steamcmd_path()
|
steamcmd_path = get_steamcmd_path()
|
||||||
show_console = subprocess.CREATE_NO_WINDOW
|
show_console = subprocess.CREATE_NO_WINDOW
|
||||||
if console:
|
if console:
|
||||||
show_console = subprocess.CREATE_NEW_CONSOLE
|
show_console = subprocess.CREATE_NEW_CONSOLE
|
||||||
|
|
||||||
process = subprocess.Popen(
|
if continuous:
|
||||||
[steamcmd_path + "\steamcmd.exe"] + command.split(),
|
while not os.path.exists(map_folder) and not stopped:
|
||||||
stdout=None if console else subprocess.PIPE,
|
process = subprocess.Popen(
|
||||||
stderr=None if console else subprocess.PIPE,
|
[steamcmd_path + "\steamcmd.exe"] + command.split(),
|
||||||
text=True,
|
stdout=None if console else subprocess.PIPE,
|
||||||
bufsize=1,
|
stderr=None if console else subprocess.PIPE,
|
||||||
universal_newlines=True,
|
text=True,
|
||||||
creationflags=show_console
|
bufsize=1,
|
||||||
)
|
universal_newlines=True,
|
||||||
|
creationflags=show_console
|
||||||
|
)
|
||||||
|
|
||||||
global steampid
|
steampid = process.pid
|
||||||
steampid = process.pid
|
|
||||||
|
|
||||||
if process.poll() is not None:
|
if process.poll() is not None:
|
||||||
return process.returncode
|
return process.returncode
|
||||||
|
|
||||||
process.communicate()
|
process.communicate()
|
||||||
|
else:
|
||||||
|
process = subprocess.Popen(
|
||||||
|
[steamcmd_path + "\steamcmd.exe"] + command.split(),
|
||||||
|
stdout=None if console else subprocess.PIPE,
|
||||||
|
stderr=None if console else subprocess.PIPE,
|
||||||
|
text=True,
|
||||||
|
bufsize=1,
|
||||||
|
universal_newlines=True,
|
||||||
|
creationflags=show_console
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
steampid = process.pid
|
||||||
|
|
||||||
|
if process.poll() is not None:
|
||||||
|
return process.returncode
|
||||||
|
|
||||||
|
process.communicate()
|
||||||
|
|
||||||
|
if not os.path.exists(map_folder):
|
||||||
|
show_message("SteamCMD has terminated", "SteamCMD has been terminated\nAnd failed to download the map/mod, try again or enable continuous download in settings")
|
||||||
|
|
||||||
show_message("SteamCMD has terminated", "SteamCMD has been terminated\nTry again if it randomly stopped!")
|
|
||||||
global stopped
|
|
||||||
stopped = True
|
stopped = True
|
||||||
self.button_download.configure(state="normal")
|
self.button_download.configure(state="normal")
|
||||||
self.button_stop.configure(state="disabled")
|
self.button_stop.configure(state="disabled")
|
||||||
|
|
||||||
return process.returncode
|
return process.returncode
|
||||||
|
|
||||||
|
|
||||||
def get_steamcmd_path():
|
def get_steamcmd_path():
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read(CONFIG_FILE_PATH)
|
config.read(CONFIG_FILE_PATH)
|
||||||
@ -237,9 +259,11 @@ def extract_json_data(json_path):
|
|||||||
data = json.load(json_file)
|
data = json.load(json_file)
|
||||||
return data["Type"], data["FolderName"]
|
return data["Type"], data["FolderName"]
|
||||||
|
|
||||||
def convert_bytes_to_readable(size_in_bytes):
|
def convert_bytes_to_readable(size_in_bytes, no_symb=None):
|
||||||
for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
|
for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
|
||||||
if size_in_bytes < 1024.0:
|
if size_in_bytes < 1024.0:
|
||||||
|
if no_symb:
|
||||||
|
return f"{size_in_bytes:.2f}"
|
||||||
return f"{size_in_bytes:.2f} {unit}"
|
return f"{size_in_bytes:.2f} {unit}"
|
||||||
size_in_bytes /= 1024.0
|
size_in_bytes /= 1024.0
|
||||||
|
|
||||||
@ -299,6 +323,11 @@ def remove_tree(folder_path, show_error=None):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def convert_seconds(seconds):
|
||||||
|
minutes, seconds = divmod(seconds, 60)
|
||||||
|
hours, minutes = divmod(minutes, 60)
|
||||||
|
return hours, minutes, seconds
|
||||||
|
|
||||||
# End helper functions
|
# End helper functions
|
||||||
|
|
||||||
class UpdateWindow(ctk.CTkToplevel):
|
class UpdateWindow(ctk.CTkToplevel):
|
||||||
@ -434,14 +463,31 @@ class SettingsTab(ctk.CTkFrame):
|
|||||||
self.checkbox_show_console_tooltip = CTkToolTip(self.checkbox_show_console, message="Toggle SteamCMD console\nPlease don't close the Console If you want to stop press the Stop button")
|
self.checkbox_show_console_tooltip = CTkToolTip(self.checkbox_show_console, message="Toggle SteamCMD console\nPlease don't close the Console If you want to stop press the Stop button")
|
||||||
self.console_var.set(self.load_settings("console"))
|
self.console_var.set(self.load_settings("console"))
|
||||||
|
|
||||||
|
# Show continuous checkbox
|
||||||
|
self.continuous_var = ctk.BooleanVar()
|
||||||
|
self.continuous_var.trace_add("write", self.enable_save_button)
|
||||||
|
self.checkbox_continuous = ctk.CTkSwitch(left_frame, text="Continuous Download", variable=self.continuous_var)
|
||||||
|
self.checkbox_continuous.grid(row=2, column=1, padx=20, pady=(20, 0), sticky="nw")
|
||||||
|
self.checkbox_continuous_tooltip = CTkToolTip(self.checkbox_continuous, message="This will make sure that the download restarts and resumes! until it finishes if steamcmd crashes randomly (it will not redownload from the start)")
|
||||||
|
self.continuous_var.set(self.load_settings("continuous_download"))
|
||||||
|
|
||||||
# clean on finish checkbox
|
# clean on finish checkbox
|
||||||
self.clean_checkbox_var = ctk.BooleanVar()
|
self.clean_checkbox_var = ctk.BooleanVar()
|
||||||
self.clean_checkbox_var.trace_add("write", self.enable_save_button)
|
self.clean_checkbox_var.trace_add("write", self.enable_save_button)
|
||||||
self.clean_checkbox = ctk.CTkSwitch(left_frame, text="Clean on finish", variable=self.clean_checkbox_var)
|
self.clean_checkbox = ctk.CTkSwitch(left_frame, text="Clean on finish", variable=self.clean_checkbox_var)
|
||||||
self.clean_checkbox.grid(row=2, column=1, padx=20, pady=(20, 0), sticky="nw")
|
self.clean_checkbox.grid(row=3, column=1, padx=20, pady=(20, 0), sticky="nw")
|
||||||
self.clean_checkbox_tooltip = CTkToolTip(self.clean_checkbox, message="Cleans the map that have been downloaded and installed from steamcmd's steamapps folder ,to save space")
|
self.clean_checkbox_tooltip = CTkToolTip(self.clean_checkbox, message="Cleans the map that have been downloaded and installed from steamcmd's steamapps folder ,to save space")
|
||||||
self.clean_checkbox_var.set(self.load_settings("clean_on_finish", "on"))
|
self.clean_checkbox_var.set(self.load_settings("clean_on_finish", "on"))
|
||||||
|
|
||||||
|
# Show estimated_progress checkbox
|
||||||
|
self.estimated_progress_var = ctk.BooleanVar()
|
||||||
|
self.estimated_progress_var.trace_add("write", self.enable_save_button)
|
||||||
|
self.estimated_progress = ctk.CTkSwitch(left_frame, text="Estimated Progress Bar", variable=self.estimated_progress_var)
|
||||||
|
self.estimated_progress.grid(row=4, column=1, padx=20, pady=(20, 0), sticky="nw")
|
||||||
|
self.estimated_progress_var_tooltip = CTkToolTip(self.estimated_progress, message="This will change how to progress bar works by estimating how long the download will take\
|
||||||
|
\nThis is not accurate ,it's better than with it off which is calculating the downloaded folder size which steamcmd dumps the full size rigth mostly")
|
||||||
|
self.estimated_progress_var.set(self.load_settings("estimated_progress", "on"))
|
||||||
|
|
||||||
# Check for updates button n Launch boiii
|
# Check for updates button n Launch boiii
|
||||||
self.check_for_updates = ctk.CTkButton(right_frame, text="Check for updates", command=self.settings_check_for_updates)
|
self.check_for_updates = ctk.CTkButton(right_frame, text="Check for updates", command=self.settings_check_for_updates)
|
||||||
self.check_for_updates.grid(row=1, column=1, padx=20, pady=(20, 0), sticky="n")
|
self.check_for_updates.grid(row=1, column=1, padx=20, pady=(20, 0), sticky="n")
|
||||||
@ -466,7 +512,7 @@ class SettingsTab(ctk.CTkFrame):
|
|||||||
|
|
||||||
def save_settings(self):
|
def save_settings(self):
|
||||||
self.save_button.configure(state='disabled')
|
self.save_button.configure(state='disabled')
|
||||||
global console, clean_on_finish
|
global console, clean_on_finish, continuous, estimated_progress
|
||||||
if self.check_updates_checkbox.get():
|
if self.check_updates_checkbox.get():
|
||||||
save_config("checkforupdtes", "on")
|
save_config("checkforupdtes", "on")
|
||||||
else:
|
else:
|
||||||
@ -486,8 +532,22 @@ class SettingsTab(ctk.CTkFrame):
|
|||||||
save_config("clean_on_finish", "off")
|
save_config("clean_on_finish", "off")
|
||||||
clean_on_finish = False
|
clean_on_finish = False
|
||||||
|
|
||||||
|
if self.checkbox_continuous.get():
|
||||||
|
save_config("continuous_download", "on")
|
||||||
|
continuous = True
|
||||||
|
else:
|
||||||
|
save_config("continuous_download", "off")
|
||||||
|
continuous = False
|
||||||
|
|
||||||
|
if self.estimated_progress.get():
|
||||||
|
save_config("estimated_progress", "on")
|
||||||
|
estimated_progress = True
|
||||||
|
else:
|
||||||
|
save_config("estimated_progress", "off")
|
||||||
|
estimated_progress = False
|
||||||
|
|
||||||
def load_settings(self, setting, fallback=None):
|
def load_settings(self, setting, fallback=None):
|
||||||
global console, clean_on_finish
|
global console, clean_on_finish, continuous, estimated_progress
|
||||||
if setting == "console":
|
if setting == "console":
|
||||||
if check_config(setting, fallback) == "on":
|
if check_config(setting, fallback) == "on":
|
||||||
console = True
|
console = True
|
||||||
@ -495,6 +555,15 @@ class SettingsTab(ctk.CTkFrame):
|
|||||||
else:
|
else:
|
||||||
console = False
|
console = False
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
if setting == "continuous_download":
|
||||||
|
if check_config(setting, "on") == "on":
|
||||||
|
continuous = True
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
continuous = False
|
||||||
|
return 0
|
||||||
|
|
||||||
if setting == "clean_on_finish":
|
if setting == "clean_on_finish":
|
||||||
if check_config(setting, fallback) == "on":
|
if check_config(setting, fallback) == "on":
|
||||||
clean_on_finish = True
|
clean_on_finish = True
|
||||||
@ -502,6 +571,13 @@ class SettingsTab(ctk.CTkFrame):
|
|||||||
else:
|
else:
|
||||||
clean_on_finish = False
|
clean_on_finish = False
|
||||||
return 0
|
return 0
|
||||||
|
if setting == "estimated_progress":
|
||||||
|
if check_config(setting, fallback) == "on":
|
||||||
|
estimated_progress = True
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
estimated_progress = False
|
||||||
|
return 0
|
||||||
else:
|
else:
|
||||||
if check_config(setting, fallback) == "on":
|
if check_config(setting, fallback) == "on":
|
||||||
return 1
|
return 1
|
||||||
@ -539,6 +615,7 @@ class BOIIIWD(ctk.CTk):
|
|||||||
self.title("BOIII Workshop Downloader - Main")
|
self.title("BOIII Workshop Downloader - Main")
|
||||||
self.geometry(f"{910}x{560}")
|
self.geometry(f"{910}x{560}")
|
||||||
self.wm_iconbitmap('ryuk.ico')
|
self.wm_iconbitmap('ryuk.ico')
|
||||||
|
self.protocol("WM_DELETE_WINDOW", self.on_closing)
|
||||||
|
|
||||||
# configure grid layout (4x4)
|
# configure grid layout (4x4)
|
||||||
self.grid_columnconfigure(1, weight=1)
|
self.grid_columnconfigure(1, weight=1)
|
||||||
@ -596,6 +673,9 @@ class BOIIIWD(ctk.CTk):
|
|||||||
self.label_speed = ctk.CTkLabel(master=self.slider_progressbar_frame, text="Network Speed: 0 KB/s")
|
self.label_speed = ctk.CTkLabel(master=self.slider_progressbar_frame, text="Network Speed: 0 KB/s")
|
||||||
self.label_speed.grid(row=1, column=0, padx=20, pady=(0, 10), sticky="w")
|
self.label_speed.grid(row=1, column=0, padx=20, pady=(0, 10), sticky="w")
|
||||||
|
|
||||||
|
self.elapsed_time = ctk.CTkLabel(master=self.slider_progressbar_frame, text="")
|
||||||
|
self.elapsed_time.grid(row=1, column=1, padx=20, pady=(0, 10), sticky="nsew", columnspan=1) # Set columnspan to 1
|
||||||
|
|
||||||
self.label_file_size = ctk.CTkLabel(master=self.slider_progressbar_frame, text="File size: 0KB")
|
self.label_file_size = ctk.CTkLabel(master=self.slider_progressbar_frame, text="File size: 0KB")
|
||||||
self.label_file_size.grid(row=1, column=2, padx=(0, 20), pady=(0, 10), sticky="e")
|
self.label_file_size.grid(row=1, column=2, padx=(0, 20), pady=(0, 10), sticky="e")
|
||||||
|
|
||||||
@ -654,6 +734,7 @@ class BOIIIWD(ctk.CTk):
|
|||||||
self.progress_bar.set(0.0)
|
self.progress_bar.set(0.0)
|
||||||
self.hide_settings_widgets()
|
self.hide_settings_widgets()
|
||||||
self.button_stop.configure(state="disabled")
|
self.button_stop.configure(state="disabled")
|
||||||
|
self.is_downloading = False
|
||||||
|
|
||||||
# sidebar windows bouttons
|
# sidebar windows bouttons
|
||||||
self.sidebar_main.configure(command=self.main_button_event, text="Main", fg_color=("#3d3d3d"))
|
self.sidebar_main.configure(command=self.main_button_event, text="Main", fg_color=("#3d3d3d"))
|
||||||
@ -673,17 +754,21 @@ class BOIIIWD(ctk.CTk):
|
|||||||
self.deiconify()
|
self.deiconify()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
global console
|
self.settings_tab.load_settings("clean_on_finish", "on")
|
||||||
if check_config("console") == "on":
|
self.settings_tab.load_settings("continuous_download", "on")
|
||||||
console = True
|
self.settings_tab.load_settings("console", "off")
|
||||||
else:
|
self.settings_tab.load_settings("estimated_progress", "on")
|
||||||
console = False
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if not check_steamcmd():
|
if not check_steamcmd():
|
||||||
self.show_warning_message()
|
self.show_warning_message()
|
||||||
|
|
||||||
|
def on_closing(self):
|
||||||
|
save_config("DestinationFolder" ,self.edit_destination_folder.get())
|
||||||
|
save_config("SteamCMDPath" ,self.edit_steamcmd_path.get())
|
||||||
|
self.stop_download(on_close=True)
|
||||||
|
os._exit(0)
|
||||||
|
|
||||||
def id_chnaged_handler(self, some=None, other=None ,shit=None):
|
def id_chnaged_handler(self, some=None, other=None ,shit=None):
|
||||||
self.after(1, self.label_file_size.configure(text=f"File size: 0KB"))
|
self.after(1, self.label_file_size.configure(text=f"File size: 0KB"))
|
||||||
@ -908,155 +993,221 @@ class BOIIIWD(ctk.CTk):
|
|||||||
text.pack()
|
text.pack()
|
||||||
|
|
||||||
def download_map(self):
|
def download_map(self):
|
||||||
global stopped
|
if not self.is_downloading:
|
||||||
stopped = False
|
self.is_downloading = True
|
||||||
|
start_down_thread = threading.Thread(target=self.download_thread)
|
||||||
|
start_down_thread.start()
|
||||||
|
else:
|
||||||
|
show_message("Warning", "Already downloading a map.")
|
||||||
|
|
||||||
save_config("DestinationFolder" ,self.edit_destination_folder.get())
|
def download_thread(self):
|
||||||
save_config("SteamCMDPath" ,self.edit_steamcmd_path.get())
|
try:
|
||||||
|
global stopped
|
||||||
|
stopped = False
|
||||||
|
|
||||||
if not check_steamcmd():
|
save_config("DestinationFolder" ,self.edit_destination_folder.get())
|
||||||
self.show_warning_message()
|
save_config("SteamCMDPath" ,self.edit_steamcmd_path.get())
|
||||||
return
|
|
||||||
|
|
||||||
steamcmd_path = get_steamcmd_path()
|
if not check_steamcmd():
|
||||||
steamcmd_exe_path = os.path.join(steamcmd_path, "steamcmd.exe")
|
self.show_warning_message()
|
||||||
steamcmd_size = os.path.getsize(steamcmd_exe_path)
|
return
|
||||||
if steamcmd_size < 3 * 1024 * 1024:
|
|
||||||
if not show_message("Warning", "SteamCMD is not initialized, Press OK to do so!\nProgram may go unresponsive until SteamCMD is finished downloading.",
|
|
||||||
icon="warning" ,exit_on_close=True):
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
initialize_steam_thread = threading.Thread(target=lambda: initialize_steam(self))
|
|
||||||
initialize_steam_thread.start()
|
|
||||||
return
|
|
||||||
|
|
||||||
workshop_id = self.edit_workshop_id.get().strip()
|
steamcmd_path = get_steamcmd_path()
|
||||||
destination_folder = self.edit_destination_folder.get().strip()
|
steamcmd_exe_path = os.path.join(steamcmd_path, "steamcmd.exe")
|
||||||
|
steamcmd_size = os.path.getsize(steamcmd_exe_path)
|
||||||
if not workshop_id.isdigit():
|
if steamcmd_size < 3 * 1024 * 1024:
|
||||||
try:
|
if not show_message("Warning", "SteamCMD is not initialized, Press OK to do so!\nProgram may go unresponsive until SteamCMD is finished downloading.",
|
||||||
if extract_workshop_id(workshop_id).strip().isdigit():
|
icon="warning" ,exit_on_close=True):
|
||||||
workshop_id = extract_workshop_id(workshop_id).strip()
|
pass
|
||||||
else:
|
else:
|
||||||
|
initialize_steam_thread = threading.Thread(target=lambda: initialize_steam(self))
|
||||||
|
initialize_steam_thread.start()
|
||||||
|
return
|
||||||
|
|
||||||
|
workshop_id = self.edit_workshop_id.get().strip()
|
||||||
|
destination_folder = self.edit_destination_folder.get().strip()
|
||||||
|
ws_file_size = get_workshop_file_size(workshop_id)
|
||||||
|
|
||||||
|
if not workshop_id.isdigit():
|
||||||
|
try:
|
||||||
|
if extract_workshop_id(workshop_id).strip().isdigit():
|
||||||
|
workshop_id = extract_workshop_id(workshop_id).strip()
|
||||||
|
else:
|
||||||
|
show_message("Warning", "Please enter a valid Workshop ID.", icon="warning")
|
||||||
|
return
|
||||||
|
except:
|
||||||
show_message("Warning", "Please enter a valid Workshop ID.", icon="warning")
|
show_message("Warning", "Please enter a valid Workshop ID.", icon="warning")
|
||||||
return
|
return
|
||||||
except:
|
|
||||||
|
file_size = ws_file_size
|
||||||
|
|
||||||
|
if not valid_id(workshop_id):
|
||||||
show_message("Warning", "Please enter a valid Workshop ID.", icon="warning")
|
show_message("Warning", "Please enter a valid Workshop ID.", icon="warning")
|
||||||
return
|
return
|
||||||
|
|
||||||
file_size = get_workshop_file_size(workshop_id)
|
if file_size is None:
|
||||||
|
show_message("Error", "Failed to retrieve file size.", icon="cancel")
|
||||||
|
return
|
||||||
|
|
||||||
if not valid_id(workshop_id):
|
if not Path(destination_folder).exists() and not destination_folder:
|
||||||
show_message("Warning", "Please enter a valid Workshop ID.", icon="warning")
|
show_message("Error", "Please select a valid destination folder.")
|
||||||
return
|
return
|
||||||
|
|
||||||
if file_size is None:
|
if not Path(steamcmd_path).exists() and not steamcmd_path.strip():
|
||||||
show_message("Error", "Failed to retrieve file size.", icon="cancel")
|
show_message("Error", "Please enter a valid SteamCMD path.")
|
||||||
return
|
return
|
||||||
|
|
||||||
if not Path(destination_folder).exists() and not destination_folder:
|
|
||||||
show_message("Error", "Please select a valid destination folder.")
|
|
||||||
return
|
|
||||||
|
|
||||||
if not Path(steamcmd_path).exists() and not steamcmd_path.strip():
|
|
||||||
show_message("Error", "Please enter a valid SteamCMD path.")
|
|
||||||
return
|
|
||||||
|
|
||||||
self.after(1, lambda mid=workshop_id: self.label_file_size.configure(text=f"File size: {get_workshop_file_size(mid ,raw=True)}"))
|
|
||||||
download_folder = os.path.join(get_steamcmd_path(), "steamapps", "workshop", "downloads", "311210", workshop_id)
|
|
||||||
map_folder = os.path.join(get_steamcmd_path(), "steamapps", "workshop", "content", "311210", workshop_id)
|
|
||||||
if not os.path.exists(download_folder):
|
|
||||||
os.makedirs(download_folder)
|
|
||||||
|
|
||||||
def check_and_update_progress():
|
|
||||||
global stopped
|
|
||||||
previous_net_speed = 0
|
|
||||||
|
|
||||||
while not stopped:
|
|
||||||
try:
|
|
||||||
current_size = sum(os.path.getsize(os.path.join(download_folder, f)) for f in os.listdir(download_folder))
|
|
||||||
except:
|
|
||||||
current_size = sum(os.path.getsize(os.path.join(map_folder, f)) for f in os.listdir(map_folder))
|
|
||||||
|
|
||||||
progress = int(current_size / file_size * 100)
|
|
||||||
self.after(1, lambda v=progress / 100.0: self.progress_bar.set(v))
|
|
||||||
|
|
||||||
current_net_speed = psutil.net_io_counters().bytes_recv
|
|
||||||
|
|
||||||
net_speed_bytes = current_net_speed - previous_net_speed
|
|
||||||
previous_net_speed = current_net_speed
|
|
||||||
|
|
||||||
net_speed, speed_unit = convert_speed(net_speed_bytes)
|
|
||||||
|
|
||||||
self.after(1, lambda v=net_speed: self.label_speed.configure(text=f"Network Speed: {v:.2f} {speed_unit}"))
|
|
||||||
self.after(1, lambda p=progress: self.progress_text.configure(text=f"{p}%"))
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
command = f"+login anonymous +workshop_download_item 311210 {workshop_id} +quit"
|
|
||||||
steamcmd_thread = threading.Thread(target=lambda: run_steamcmd_command(command, self))
|
|
||||||
steamcmd_thread.start()
|
|
||||||
|
|
||||||
def wait_for_threads():
|
|
||||||
update_ui_thread = threading.Thread(target=check_and_update_progress)
|
|
||||||
update_ui_thread.daemon = True
|
|
||||||
update_ui_thread.start()
|
|
||||||
update_ui_thread.join()
|
|
||||||
|
|
||||||
global stopped
|
|
||||||
stopped = True
|
|
||||||
|
|
||||||
self.label_speed.configure(text="Network Speed: 0 KB/s")
|
|
||||||
self.progress_text.configure(text="0%")
|
|
||||||
self.progress_bar.set(0.0)
|
|
||||||
|
|
||||||
|
self.after(1, lambda mid=workshop_id: self.label_file_size.configure(text=f"File size: {get_workshop_file_size(mid ,raw=True)}"))
|
||||||
|
download_folder = os.path.join(get_steamcmd_path(), "steamapps", "workshop", "downloads", "311210", workshop_id)
|
||||||
map_folder = os.path.join(get_steamcmd_path(), "steamapps", "workshop", "content", "311210", workshop_id)
|
map_folder = os.path.join(get_steamcmd_path(), "steamapps", "workshop", "content", "311210", workshop_id)
|
||||||
|
if not os.path.exists(download_folder):
|
||||||
|
os.makedirs(download_folder)
|
||||||
|
|
||||||
json_file_path = os.path.join(map_folder, "workshop.json")
|
def check_and_update_progress():
|
||||||
|
# delay untill steam boots up and starts downloading (ive a better idea ill implement it later)
|
||||||
|
time.sleep(8)
|
||||||
|
global stopped
|
||||||
|
previous_net_speed = 0
|
||||||
|
est_downloaded_bytes = 0
|
||||||
|
start_time = time.time()
|
||||||
|
file_size = ws_file_size
|
||||||
|
|
||||||
if os.path.exists(json_file_path):
|
while not stopped:
|
||||||
mod_type, folder_name = extract_json_data(json_file_path)
|
try:
|
||||||
|
current_size = sum(os.path.getsize(os.path.join(download_folder, f)) for f in os.listdir(download_folder))
|
||||||
|
except:
|
||||||
|
current_size = sum(os.path.getsize(os.path.join(map_folder, f)) for f in os.listdir(map_folder))
|
||||||
|
|
||||||
if mod_type == "mod":
|
progress = int(current_size / file_size * 100)
|
||||||
mods_folder = os.path.join(destination_folder, "mods")
|
|
||||||
folder_name_path = os.path.join(mods_folder, folder_name, "zone")
|
|
||||||
elif mod_type == "map":
|
|
||||||
usermaps_folder = os.path.join(destination_folder, "usermaps")
|
|
||||||
folder_name_path = os.path.join(usermaps_folder, folder_name, "zone")
|
|
||||||
else:
|
|
||||||
show_message("Error", "Invalid map type in workshop.json.", icon="cancel")
|
|
||||||
return
|
|
||||||
|
|
||||||
os.makedirs(folder_name_path, exist_ok=True)
|
if progress > 100:
|
||||||
|
progress = int(current_size / current_size * 100)
|
||||||
|
file_size = current_size
|
||||||
|
self.after(1, lambda p=progress: self.label_file_size.configure(text=f"Wrong size reported\nActual size: ~{convert_bytes_to_readable(current_size)}"))
|
||||||
|
|
||||||
try:
|
if estimated_progress:
|
||||||
shutil.copytree(map_folder, folder_name_path, dirs_exist_ok=True)
|
time_elapsed = time.time() - start_time
|
||||||
except Exception as E:
|
raw_net_speed = psutil.net_io_counters().bytes_recv
|
||||||
show_message("Error", f"Error copying files: {E}", icon="cancel")
|
|
||||||
|
|
||||||
if clean_on_finish:
|
current_net_speed_text = raw_net_speed
|
||||||
remove_tree(map_folder)
|
net_speed_bytes = current_net_speed_text - previous_net_speed
|
||||||
remove_tree(download_folder)
|
previous_net_speed = current_net_speed_text
|
||||||
|
|
||||||
msg = CTkMessagebox(title="Download Complete", message=f"{mod_type.capitalize()} files were downloaded\nYou can run the game now!", icon="info", option_1="Launch", option_2="Ok")
|
current_net_speed = net_speed_bytes
|
||||||
response = msg.get()
|
down_cap = 150000000
|
||||||
if response=="Launch":
|
if current_net_speed >= down_cap:
|
||||||
launch_boiii_func(self.edit_destination_folder.get().strip())
|
current_net_speed = 264029
|
||||||
if response=="Ok":
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.button_download.configure(state="normal")
|
est_downloaded_bytes += current_net_speed
|
||||||
self.button_stop.configure(state="disabled")
|
|
||||||
|
|
||||||
update_wait_thread = threading.Thread(target=wait_for_threads)
|
percentage_complete = (est_downloaded_bytes / file_size) * 100
|
||||||
update_wait_thread.start()
|
|
||||||
|
|
||||||
self.button_download.configure(state="disabled")
|
progress = min(percentage_complete / 100, 0.99)
|
||||||
self.button_stop.configure(state="normal")
|
|
||||||
|
|
||||||
def stop_download(self):
|
net_speed, speed_unit = convert_speed(net_speed_bytes)
|
||||||
|
|
||||||
|
elapsed_hours, elapsed_minutes, elapsed_seconds = convert_seconds(time_elapsed)
|
||||||
|
|
||||||
|
print(f"raw_net {raw_net_speed}\ncurrent_net_speed: {current_net_speed}\nest_downloaded_bytes {est_downloaded_bytes}\npercentage_complete {percentage_complete}\nprogress {progress}")
|
||||||
|
|
||||||
|
self.after(1, self.progress_bar.set(progress))
|
||||||
|
self.after(1, lambda v=net_speed: self.label_speed.configure(text=f"Network Speed: {v:.2f} {speed_unit}"))
|
||||||
|
self.after(1, lambda p=percentage_complete: self.progress_text.configure(text=f"{p:.2f}%"))
|
||||||
|
self.after(1, lambda h=elapsed_hours, m=elapsed_minutes, s=elapsed_seconds: self.elapsed_time.configure(text=f"Elapsed Time: {int(h):02d}:{int(m):02d}:{int(s):02d}"))
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
else:
|
||||||
|
time_elapsed = time.time() - start_time
|
||||||
|
progress = int(current_size / file_size * 100)
|
||||||
|
self.after(1, lambda v=progress / 100.0: self.progress_bar.set(v))
|
||||||
|
|
||||||
|
current_net_speed = psutil.net_io_counters().bytes_recv
|
||||||
|
|
||||||
|
net_speed_bytes = current_net_speed - previous_net_speed
|
||||||
|
previous_net_speed = current_net_speed
|
||||||
|
|
||||||
|
net_speed, speed_unit = convert_speed(net_speed_bytes)
|
||||||
|
elapsed_hours, elapsed_minutes, elapsed_seconds = convert_seconds(time_elapsed)
|
||||||
|
|
||||||
|
self.after(1, lambda v=net_speed: self.label_speed.configure(text=f"Network Speed: {v:.2f} {speed_unit}"))
|
||||||
|
self.after(1, lambda p=progress: self.progress_text.configure(text=f"{p}%"))
|
||||||
|
self.after(1, lambda h=elapsed_hours, m=elapsed_minutes, s=elapsed_seconds: self.elapsed_time.configure(text=f"Elapsed Time: {int(h):02d}:{int(m):02d}:{int(s):02d}"))
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
command = f"+login anonymous +@sSteamCmdForcePlatformBitness 64 +app_info_update 1 +app_info_print 311210 app_update 311210 +workshop_download_item 311210 {workshop_id} validate +quit"
|
||||||
|
steamcmd_thread = threading.Thread(target=lambda: run_steamcmd_command(command, self, map_folder))
|
||||||
|
steamcmd_thread.start()
|
||||||
|
|
||||||
|
def wait_for_threads():
|
||||||
|
update_ui_thread = threading.Thread(target=check_and_update_progress)
|
||||||
|
update_ui_thread.daemon = True
|
||||||
|
update_ui_thread.start()
|
||||||
|
update_ui_thread.join()
|
||||||
|
|
||||||
|
global stopped
|
||||||
|
stopped = True
|
||||||
|
|
||||||
|
self.label_speed.configure(text="Network Speed: 0 KB/s")
|
||||||
|
self.progress_text.configure(text="0%")
|
||||||
|
self.progress_bar.set(0.0)
|
||||||
|
|
||||||
|
map_folder = os.path.join(get_steamcmd_path(), "steamapps", "workshop", "content", "311210", workshop_id)
|
||||||
|
|
||||||
|
json_file_path = os.path.join(map_folder, "workshop.json")
|
||||||
|
|
||||||
|
if os.path.exists(json_file_path):
|
||||||
|
mod_type, folder_name = extract_json_data(json_file_path)
|
||||||
|
|
||||||
|
if mod_type == "mod":
|
||||||
|
mods_folder = os.path.join(destination_folder, "mods")
|
||||||
|
folder_name_path = os.path.join(mods_folder, folder_name, "zone")
|
||||||
|
elif mod_type == "map":
|
||||||
|
usermaps_folder = os.path.join(destination_folder, "usermaps")
|
||||||
|
folder_name_path = os.path.join(usermaps_folder, folder_name, "zone")
|
||||||
|
else:
|
||||||
|
show_message("Error", "Invalid map type in workshop.json.", icon="cancel")
|
||||||
|
return
|
||||||
|
|
||||||
|
os.makedirs(folder_name_path, exist_ok=True)
|
||||||
|
|
||||||
|
try:
|
||||||
|
shutil.copytree(map_folder, folder_name_path, dirs_exist_ok=True)
|
||||||
|
except Exception as E:
|
||||||
|
show_message("Error", f"Error copying files: {E}", icon="cancel")
|
||||||
|
|
||||||
|
if clean_on_finish:
|
||||||
|
remove_tree(map_folder)
|
||||||
|
remove_tree(download_folder)
|
||||||
|
|
||||||
|
msg = CTkMessagebox(title="Download Complete", message=f"{mod_type.capitalize()} files were downloaded\nYou can run the game now!", icon="info", option_1="Launch", option_2="Ok")
|
||||||
|
response = msg.get()
|
||||||
|
if response=="Launch":
|
||||||
|
launch_boiii_func(self.edit_destination_folder.get().strip())
|
||||||
|
if response=="Ok":
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.button_download.configure(state="normal")
|
||||||
|
self.button_stop.configure(state="disabled")
|
||||||
|
|
||||||
|
update_wait_thread = threading.Thread(target=wait_for_threads)
|
||||||
|
update_wait_thread.start()
|
||||||
|
|
||||||
|
self.button_download.configure(state="disabled")
|
||||||
|
self.button_stop.configure(state="normal")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
self.stop_download
|
||||||
|
self.is_downloading = False
|
||||||
|
|
||||||
|
def stop_download(self, on_close=None):
|
||||||
global stopped
|
global stopped
|
||||||
stopped = True
|
stopped = True
|
||||||
|
|
||||||
|
if on_close:
|
||||||
|
subprocess.run(['taskkill', '/F', '/IM', 'steamcmd.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||||
|
creationflags=subprocess.CREATE_NO_WINDOW)
|
||||||
|
return
|
||||||
|
|
||||||
subprocess.run(['taskkill', '/F', '/IM', 'steamcmd.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
subprocess.run(['taskkill', '/F', '/IM', 'steamcmd.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||||
creationflags=subprocess.CREATE_NO_WINDOW)
|
creationflags=subprocess.CREATE_NO_WINDOW)
|
||||||
|
|
||||||
@ -1064,6 +1215,7 @@ class BOIIIWD(ctk.CTk):
|
|||||||
self.button_stop.configure(state="disabled")
|
self.button_stop.configure(state="disabled")
|
||||||
self.label_speed.configure(text="Network Speed: 0 KB/s")
|
self.label_speed.configure(text="Network Speed: 0 KB/s")
|
||||||
self.progress_text.configure(text="0%")
|
self.progress_text.configure(text="0%")
|
||||||
|
self.elapsed_time.configure(text=f"")
|
||||||
self.progress_bar.set(0.0)
|
self.progress_bar.set(0.0)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
Loading…
Reference in New Issue
Block a user