v0.2.4 preview

This commit is contained in:
faroukbmiled 2023-08-29 20:02:57 +01:00
parent 10ac2564ea
commit 2af9cd8ddb
2 changed files with 312 additions and 183 deletions

View File

@ -20,28 +20,13 @@ import io
import os
import re
VERSION = "v0.2.3"
VERSION = "v0.2.4"
GITHUB_REPO = "faroukbmiled/BOIIIWD"
LATEST_RELEASE_URL = "https://github.com/faroukbmiled/BOIIIWD/releases/latest/download/Release.zip"
UPDATER_FOLDER = "update"
CONFIG_FILE_PATH = "config.ini"
RESOURCES_DIR = os.path.join(os.path.dirname(__file__), 'resources')
# fuck it we ball, ill get rid of globals when i finish everything cant be bothered rn
global stopped, steampid, console, clean_on_finish, continuous, estimated_progress, steam_fail_counter, \
steam_fail_counter_toggle, steam_fail_number, steamcmd_reset, show_fails
steampid = None
stopped = False
console = False
clean_on_finish = True
continuous = True
estimated_progress = True
steam_fail_counter_toggle = False
steam_fail_counter = 0
steam_fail_number = 10
steamcmd_reset = False
show_fails = True
# Start Helper Functions
def cwd():
if getattr(sys, 'frozen', False):
@ -73,6 +58,7 @@ def check_custom_theme(theme_name):
except:
return os.path.join(RESOURCES_DIR, "boiiiwd_theme.json")
# theme initialization
ctk.set_appearance_mode(check_config("appearance", "Dark")) # Modes: "System" (standard), "Dark", "Light"
try:
ctk.set_default_color_theme(check_custom_theme(check_config("theme", fallback="boiiiwd_theme.json")))
@ -218,84 +204,6 @@ def create_default_config():
with open(CONFIG_FILE_PATH, "w") as config_file:
config.write(config_file)
def run_steamcmd_command(command, self, map_folder, queue=None):
global steampid, stopped, steam_fail_counter, steam_fail_number, steamcmd_reset
steamcmd_path = get_steamcmd_path()
show_console = subprocess.CREATE_NO_WINDOW
if console:
show_console = subprocess.CREATE_NEW_CONSOLE
if os.path.exists(map_folder):
try:
try:
os.remove(map_folder)
except:
timestamp = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
os.rename(map_folder, os.path.join(map_folder, os.path.join(get_steamcmd_path(), "steamapps", "workshop", "content", "311210", f"couldntremove_{timestamp}")))
except Exception as e:
stopped = True
self.queue_stop_button = True
show_message("Error", f"Couldn't remove {map_folder}, please do so manually\n{e}", icon="cancel")
return
if continuous:
while not os.path.exists(map_folder) and not stopped:
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()
steam_fail_counter = steam_fail_counter + 1
if steam_fail_counter_toggle:
# print(steam_fail_counter)
try:
if steam_fail_counter >= int(steam_fail_number):
reset_steamcmd(no_warn=True)
steamcmd_reset = True
steam_fail_counter = 0
except:
if steam_fail_counter >= 10:
reset_steamcmd(no_warn=True)
steam_fail_counter = 0
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")
stopped = True
if not queue:
self.button_download.configure(state="normal")
self.button_stop.configure(state="disabled")
return process.returncode
def get_steamcmd_path():
config = configparser.ConfigParser()
config.read(CONFIG_FILE_PATH)
@ -353,9 +261,15 @@ def show_message(title, message, icon="warning", exit_on_close=False):
msg = CTkMessagebox(title=title, message=message, icon=icon)
def launch_boiii_func(path):
procname = "boiii.exe"
try:
boiii_path = os.path.join(path, "boiii.exe")
subprocess.Popen([boiii_path], cwd=path)
if procname in (p.name() for p in psutil.process_iter()):
for proc in psutil.process_iter():
if proc.name() == procname:
proc.kill()
boiii_path = os.path.join(path, procname)
subprocess.Popen([boiii_path ,"-launch"] , cwd=path)
show_message("Please wait!", "The game has launched in the background it will open up in a sec!", icon="info")
except Exception as e:
show_message("Error: Failed to launch BOIII", f"Failed to launch boiii.exe\nMake sure to put in your correct boiii path\n{e}")
@ -639,6 +553,7 @@ class LibraryTab(ctk.CTkScrollableFrame):
button_view_list.destroy()
self.label_list.remove(label)
self.button_list.remove(button)
self.added_items.remove(label.cget("text"))
self.button_view_list.remove(button_view_list)
def refresh_items(self):
@ -829,6 +744,18 @@ class LibraryTab(ctk.CTkScrollableFrame):
class SettingsTab(ctk.CTkFrame):
def __init__(self, master=None):
super().__init__(master)
# settings default bools
self.skip_already_installed = True
self.stopped = False
self.console = False
self.clean_on_finish = True
self.continuous = True
self.estimated_progress = True
self.steam_fail_counter_toggle = False
self.steam_fail_counter = 0
self.steam_fail_number = 10
self.steamcmd_reset = False
self.show_fails = True
# Left and right frames, use fg_color="transparent"
self.grid_rowconfigure(0, weight=1)
@ -876,27 +803,35 @@ class SettingsTab(ctk.CTkFrame):
# 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\
self.estimated_progress_cb = ctk.CTkSwitch(left_frame, text="Estimated Progress Bar", variable=self.estimated_progress_var)
self.estimated_progress_cb.grid(row=4, column=1, padx=20, pady=(20, 0), sticky="nw")
self.estimated_progress_var_tooltip = CTkToolTip(self.estimated_progress_cb, 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"))
# Show estimated_progress checkbox
# Show show fails checkbox
self.show_fails_var = ctk.BooleanVar()
self.show_fails_var.trace_add("write", self.enable_save_button)
self.show_fails = ctk.CTkSwitch(left_frame, text="Show fails (on top of progress bar):", variable=self.show_fails_var)
self.show_fails.grid(row=5, column=1, padx=20, pady=(20, 0), sticky="nw")
self.show_fails_tooltip = CTkToolTip(self.show_fails, message="Display how many times steamcmd has failed/crashed\nIf the number is getting high quickly then try pressing Reset SteamCMD and try again, otherwise its fine")
self.show_fails_cb = ctk.CTkSwitch(left_frame, text="Show fails (on top of progress bar):", variable=self.show_fails_var)
self.show_fails_cb.grid(row=5, column=1, padx=20, pady=(20, 0), sticky="nw")
self.show_fails_tooltip = CTkToolTip(self.show_fails_cb, message="Display how many times steamcmd has failed/crashed\nIf the number is getting high quickly then try pressing Reset SteamCMD and try again, otherwise its fine")
self.estimated_progress_var.set(self.load_settings("show_fails", "on"))
# Show skip_already_installed maps checkbox
self.skip_already_installed_var = ctk.BooleanVar()
self.skip_already_installed_var.trace_add("write", self.enable_save_button)
self.skip_already_installed_ch = ctk.CTkSwitch(left_frame, text="Skip already installed maps:", variable=self.skip_already_installed_var)
self.skip_already_installed_ch.grid(row=6, column=1, padx=20, pady=(20, 0), sticky="nw")
self.skip_already_installed_ch_tooltip = CTkToolTip(self.skip_already_installed_ch, message="If on it will not download installed maps,\nthis can miss sometimes if you remove maps manually and not from library tab while the app is running")
self.skip_already_installed_var.set(self.load_settings("skip_already_installed", "on"))
# Resetr steam on many fails
self.reset_steamcmd_on_fail_var = ctk.IntVar()
self.reset_steamcmd_on_fail_var.trace_add("write", self.enable_save_button)
self.reset_steamcmd_on_fail_text = ctk.CTkLabel(left_frame, text=f"Reset steamcmd on % fails: (n of fails)", anchor="w")
self.reset_steamcmd_on_fail_text.grid(row=6, column=1, padx=20, pady=(10, 0), sticky="nw")
self.reset_steamcmd_on_fail_text.grid(row=7, column=1, padx=20, pady=(10, 0), sticky="nw")
self.reset_steamcmd_on_fail = ctk.CTkOptionMenu(left_frame, values=["20", "30", "40", "Custom", "Disable"], variable=self.reset_steamcmd_on_fail_var, command=self.reset_steamcmd_on_fail_func)
self.reset_steamcmd_on_fail.grid(row=7, column=1, padx=20, pady=(0, 0), sticky="nw")
self.reset_steamcmd_on_fail.grid(row=8, column=1, padx=20, pady=(0, 0), sticky="nw")
self.reset_steamcmd_on_fail_tooltip = CTkToolTip(self.reset_steamcmd_on_fail, message="This actually fixes steamcmd when its crashing way too much")
self.reset_steamcmd_on_fail.set(value=self.load_settings("reset_on_fail", "Disable"))
@ -976,7 +911,6 @@ class SettingsTab(ctk.CTkFrame):
def save_settings(self):
self.save_button.configure(state='disabled')
global console, clean_on_finish, continuous, estimated_progress, steam_fail_number, steam_fail_counter_toggle, show_fails
if self.check_updates_checkbox.get():
save_config("checkforupdtes", "on")
else:
@ -984,104 +918,118 @@ class SettingsTab(ctk.CTkFrame):
if self.checkbox_show_console.get():
save_config("console", "on")
console = True
self.console = True
else:
save_config("console", "off")
console = False
self.console = False
if self.skip_already_installed_ch.get():
save_config("skip_already_installed", "on")
self.skip_already_installed = True
else:
save_config("skip_already_installed", "off")
self.skip_already_installed = False
if self.clean_checkbox.get():
save_config("clean_on_finish", "on")
clean_on_finish = True
self.clean_on_finish = True
else:
save_config("clean_on_finish", "off")
clean_on_finish = False
self.clean_on_finish = False
if self.checkbox_continuous.get():
save_config("continuous_download", "on")
continuous = True
self.continuous = True
else:
save_config("continuous_download", "off")
continuous = False
self.continuous = False
if self.estimated_progress.get():
if self.estimated_progress_cb.get():
save_config("estimated_progress", "on")
estimated_progress = True
self.estimated_progress = True
else:
save_config("estimated_progress", "off")
estimated_progress = False
self.estimated_progress = False
if self.show_fails.get():
if self.show_fails_cb.get():
save_config("show_fails", "on")
show_fails = True
self.show_fails = True
else:
save_config("show_fails", "off")
show_fails = False
self.show_fails = False
if self.reset_steamcmd_on_fail.get():
value = self.reset_steamcmd_on_fail.get()
if value == "Disable":
steam_fail_counter_toggle = False
self.steam_fail_counter_toggle = False
else:
steam_fail_counter_toggle = True
steam_fail_number = int(value)
self.steam_fail_counter_toggle = True
self.steam_fail_number = int(value)
save_config("reset_on_fail", value)
def load_settings(self, setting, fallback=None):
global console, clean_on_finish, continuous, estimated_progress, steam_fail_counter_toggle, steam_fail_number, show_fails
if setting == "console":
if check_config(setting, fallback) == "on":
console = True
self.console = True
return 1
else:
console = False
self.console = False
return 0
if setting == "continuous_download":
if check_config(setting, "on") == "on":
continuous = True
self.continuous = True
return 1
else:
continuous = False
self.continuous = False
return 0
if setting == "clean_on_finish":
if check_config(setting, fallback) == "on":
clean_on_finish = True
self.clean_on_finish = True
return 1
else:
clean_on_finish = False
self.clean_on_finish = False
return 0
if setting == "estimated_progress":
if check_config(setting, fallback) == "on":
estimated_progress = True
self.estimated_progress = True
return 1
else:
estimated_progress = False
self.estimated_progress = False
return 0
if setting == "reset_on_fail":
option = check_config(setting, fallback)
if option == "Disable" or option == "Custom":
steam_fail_counter_toggle = False
self.steam_fail_counter_toggle = False
return "Disable"
else:
try:
steam_fail_number = int(option)
self.steam_fail_number = int(option)
return option
except:
if steam_fail_counter_toggle:
steam_fail_number = 10
if self.steam_fail_counter_toggle:
self.steam_fail_number = 10
return "10"
else:
steam_fail_number = 10
self.steam_fail_number = 10
return "Disable"
if setting == "show_fails":
if check_config(setting, fallback) == "on":
show_fails = True
self.show_fails = True
return 1
else:
show_fails = False
self.show_fails = False
return 0
if setting == "skip_already_installed":
if check_config(setting, fallback) == "on":
self.skip_already_installed = True
return 1
else:
self.skip_already_installed = False
return 0
if setting == "theme":
@ -1099,6 +1047,8 @@ class SettingsTab(ctk.CTkFrame):
else:
return 0
def boiiiwd_custom_theme(self, disable_only=None):
file_to_rename = os.path.join(cwd(), "boiiiwd_theme.json")
if os.path.exists(file_to_rename):
@ -1128,6 +1078,7 @@ class SettingsTab(ctk.CTkFrame):
self.clean_checkbox_var.set(self.load_settings("clean_on_finish", "on"))
self.continuous_var.set(self.load_settings("continuous_download"))
self.show_fails_var.set(self.load_settings("show_fails", "on"))
self.skip_already_installed_var.set(self.load_settings("skip_already_installed", "on"))
# keep last cuz of trace_add()
self.save_button.configure(state='disabled')
@ -1309,6 +1260,7 @@ class BOIIIWD(ctk.CTk):
self.is_pressed = False
self.queue_enabled = False
self.queue_stop_button = False
self.is_downloading = False
# sidebar windows bouttons
self.sidebar_main.configure(command=self.main_button_event, text="Main ⬇️", fg_color=(self.active_color), state="active")
@ -1337,6 +1289,7 @@ class BOIIIWD(ctk.CTk):
self.settings_tab.load_settings("estimated_progress", "on")
self.settings_tab.load_settings("reset_on_fail", "Disable")
self.settings_tab.load_settings("show_fails", "on")
self.settings_tab.load_settings("skip_already_installed", "on")
except:
pass
@ -1473,7 +1426,7 @@ class BOIIIWD(ctk.CTk):
create_default_config()
def help_queue_text_func(self):
if any(char.isalpha() for char in self.queuetextarea.get("1.0", "end")):
if any(char.strip() for char in self.queuetextarea.get("1.0", "end")):
self.workshop_queue_label.configure(text="Workshop IDs/Links => press help to see examples:")
self.queuetextarea.configure(state="normal")
self.queuetextarea.delete(1.0, "end")
@ -1702,9 +1655,148 @@ class BOIIIWD(ctk.CTk):
top.grid_columnconfigure(0, weight=1)
top.grid_columnconfigure(1, weight=1)
def check_steamcmd_stdout(self, log_file_path, target_item_id):
temp_file_path = log_file_path + '.temp'
shutil.copy2(log_file_path, temp_file_path)
try:
with open(temp_file_path, 'r') as log_file:
log_file.seek(0, os.SEEK_END)
file_size = log_file.tell()
position = file_size
lines_found = 0
while lines_found < 7 and position > 0:
position -= 1
log_file.seek(position, os.SEEK_SET)
char = log_file.read(1)
if char == '\n':
lines_found += 1
lines = log_file.readlines()[-7:]
for line in reversed(lines):
line = line.lower().strip()
if f"download item {target_item_id.strip()}" in line:
return True
return False
finally:
os.remove(temp_file_path)
# the real deal
def run_steamcmd_command(self, command, map_folder, wsid, queue=None):
steamcmd_path = get_steamcmd_path()
stdout = os.path.join(steamcmd_path, "logs", "workshop_log.txt")
timestamp = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
try:
with open(stdout, 'w') as file:
file.write('')
except:
os.rename(stdout, os.path.join(map_folder, os.path.join(stdout, f"workshop_log_couldntremove_{timestamp}.txt")))
show_console = subprocess.CREATE_NO_WINDOW
if self.settings_tab.console:
show_console = subprocess.CREATE_NEW_CONSOLE
if os.path.exists(map_folder):
try:
try:
os.remove(map_folder)
except:
os.rename(map_folder, os.path.join(map_folder, os.path.join(get_steamcmd_path(), "steamapps", "workshop", "content", "311210", f"couldntremove_{timestamp}")))
except Exception as e:
self.settings_tab.stopped = True
self.queue_stop_button = True
show_message("Error", f"Couldn't remove {map_folder}, please do so manually\n{e}", icon="cancel")
self.stop_download
return
if self.settings_tab.continuous:
while not os.path.exists(map_folder) and not self.settings_tab.stopped:
process = subprocess.Popen(
[steamcmd_path + "\steamcmd.exe"] + command.split(),
stdout=None if self.settings_tab.console else subprocess.PIPE,
stderr=None if self.settings_tab.console else subprocess.PIPE,
text=True,
bufsize=1,
universal_newlines=True,
creationflags=show_console
)
#wait for process
while True:
if not self.is_downloading:
if self.check_steamcmd_stdout(stdout, wsid):
self.is_downloading = True
if process.poll() != None:
break
time.sleep(1)
# print("Broken freeeee!")
self.is_downloading = False
try:
with open(stdout, 'w') as file:
file.write('')
except:
os.rename(stdout, os.path.join(map_folder, os.path.join(stdout, f"workshop_log_couldntremove_{timestamp}.txt")))
self.settings_tab.steam_fail_counter = self.settings_tab.steam_fail_counter + 1
if self.settings_tab.steam_fail_counter_toggle:
try:
if self.settings_tab.steam_fail_counter >= int(self.settings_tab.steam_fail_number):
reset_steamcmd(no_warn=True)
self.settings_tab.steamcmd_reset = True
self.settings_tab.steam_fail_counter = 0
except:
if self.settings_tab.steam_fail_counter >= 10:
reset_steamcmd(no_warn=True)
self.settings_tab.steam_fail_counter = 0
else:
process = subprocess.Popen(
[steamcmd_path + "\steamcmd.exe"] + command.split(),
stdout=None if self.settings_tab.console else subprocess.PIPE,
stderr=None if self.settings_tab.console else subprocess.PIPE,
text=True,
bufsize=1,
universal_newlines=True,
creationflags=show_console
)
while True:
if not self.is_downloading:
if self.find_download_event(stdout, wsid):
self.is_downloading = True
if process.poll() != None:
break
time.sleep(1)
# print("Broken freeeee!")
self.is_downloading = False
try:
with open(stdout, 'w') as file:
file.write('')
except:
os.rename(stdout, os.path.join(map_folder, os.path.join(stdout, f"workshop_log_couldntremove_{timestamp}.txt")))
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")
self.settings_tab.stopped = True
if not queue:
self.button_download.configure(state="normal")
self.button_stop.configure(state="disabled")
return process.returncode
def download_map(self):
self.is_downloading = False
if not self.is_pressed:
self.is_pressed = True
self.library_tab.load_items(self.edit_destination_folder.get())
if self.queue_enabled:
start_down_thread = threading.Thread(target=self.queue_download_thread)
start_down_thread.start()
@ -1715,8 +1807,7 @@ class BOIIIWD(ctk.CTk):
show_message("Warning", "Already pressed, Please wait.")
def queue_download_thread(self):
global stopped
stopped = False
self.stopped = False
self.queue_stop_button = False
try:
save_config("DestinationFolder" ,self.edit_destination_folder.get())
@ -1762,6 +1853,7 @@ class BOIIIWD(ctk.CTk):
return
self.total_queue_size = 0
self.already_installed = []
for item in items:
item.strip()
workshop_id = item
@ -1791,16 +1883,32 @@ class BOIIIWD(ctk.CTk):
self.stop_download
return
if any(workshop_id in item for item in self.library_tab.added_items):
self.already_installed.append(workshop_id)
if self.already_installed:
item_ids = ", ".join(self.already_installed)
if self.settings_tab.skip_already_installed:
for item in self.already_installed:
if item in items:
items.remove(item)
show_message("Heads up!, map/s skipped => skip is on in settings", f"These item IDs may already be installed and are skipped:\n{item_ids}", icon="info")
if not any(isinstance(item, int) for item in items):
self.stop_download
return
show_message("Heads up! map/s not skipped => skip is off in settings", f"These item IDs may already be installed:\n{item_ids}", icon="info")
self.after(1, self.status_text.configure(text=f"Status: Total size: ~{convert_bytes_to_readable(self.total_queue_size)}"))
start_time = time.time()
for index, item in enumerate(items):
self.settings_tab.steam_fail_counter = 0
current_number = index + 1
total_items = len(items)
if self.queue_stop_button:
self.stop_download
break
item.strip()
stopped = False
self.settings_tab.stopped = False
workshop_id = item
if not workshop_id.isdigit():
try:
@ -1823,17 +1931,14 @@ class BOIIIWD(ctk.CTk):
os.makedirs(download_folder)
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, steamcmd_reset
previous_net_speed = 0
est_downloaded_bytes = 0
file_size = ws_file_size
item_name = get_item_name(workshop_id) if get_item_name(workshop_id) else "Error getting name"
while not stopped:
if steamcmd_reset:
steamcmd_reset = False
while not self.settings_tab.stopped:
if self.settings_tab.steamcmd_reset:
self.settings_tab.steamcmd_reset = False
previous_net_speed = 0
est_downloaded_bytes = 0
@ -1856,7 +1961,19 @@ class BOIIIWD(ctk.CTk):
text=f"Status: Total size: ~{convert_bytes_to_readable(self.total_queue_size)} | ID: {workshop_id} | {item_name} | Downloading {current_number}/{total_items}"))
self.after(1, lambda p=progress: self.label_file_size.configure(text=f"Wrong size reported\nFile size: ~{convert_bytes_to_readable(current_size)}"))
if estimated_progress:
while not self.is_downloading:
self.after(1, self.label_speed.configure(text=f"Network Speed: 0 KB/s"))
time_elapsed = time.time() - start_time
elapsed_hours, elapsed_minutes, elapsed_seconds = convert_seconds(time_elapsed)
if self.settings_tab.show_fails:
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} - Fails: {self.settings_tab.steam_fail_counter}"))
else:
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)
if self.is_downloading:
break
if self.settings_tab.estimated_progress:
time_elapsed = time.time() - start_time
raw_net_speed = psutil.net_io_counters().bytes_recv
@ -1885,8 +2002,8 @@ class BOIIIWD(ctk.CTk):
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=min(percentage_complete ,99): self.progress_text.configure(text=f"{p:.2f}%"))
if show_fails:
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} - Fails: {steam_fail_counter}"))
if self.settings_tab.show_fails:
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} - Fails: {self.settings_tab.steam_fail_counter}"))
else:
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}"))
@ -1908,14 +2025,14 @@ class BOIIIWD(ctk.CTk):
text=f"Status: Total size: ~{convert_bytes_to_readable(self.total_queue_size)} | ID: {workshop_id} | {item_name} | Downloading {current_number}/{total_items}"))
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}%"))
if show_fails:
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} - Fails: {steam_fail_counter}"))
if self.settings_tab.show_fails:
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} - Fails: {self.settings_tab.steam_fail_counter}"))
else:
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, queue=True))
command = f"+login anonymous app_update 311210 +workshop_download_item 311210 {workshop_id} validate +quit"
steamcmd_thread = threading.Thread(target=lambda: self.run_steamcmd_command(command, map_folder, workshop_id, queue=True))
steamcmd_thread.start()
def wait_for_threads():
@ -1954,12 +2071,12 @@ class BOIIIWD(ctk.CTk):
except Exception as E:
show_message("Error", f"Error copying files: {E}", icon="cancel")
if clean_on_finish:
if self.settings_tab.clean_on_finish:
remove_tree(map_folder)
remove_tree(download_folder)
if index == len(items) - 1:
msg = CTkMessagebox(title="Downloads Complete", message=f"All files were downloaded\nYou can run the game now!", icon="info", option_1="Launch", option_2="Ok")
msg = CTkMessagebox(title="Downloads Complete", message=f"All files were downloaded\nYou can run the game now!\nPS: You have to restart the game \n(pressing launch will launch/restarts)", icon="info", option_1="Launch", option_2="Ok")
response = msg.get()
if response=="Launch":
launch_boiii_func(self.edit_destination_folder.get().strip())
@ -1978,20 +2095,18 @@ class BOIIIWD(ctk.CTk):
self.button_stop.configure(state="disabled")
self.after(1, self.status_text.configure(text=f"Status: Done"))
self.after(1, self.label_file_size.configure(text=f"File size: 0KB"))
stopped = True
self.settings_tab.stopped = True
self.stop_download
return
finally:
global steam_fail_counter
steam_fail_counter = 0
self.settings_tab.steam_fail_counter = 0
self.after(1, self.label_file_size.configure(text=f"File size: 0KB"))
self.stop_download
self.is_pressed = False
def download_thread(self):
try:
global stopped
stopped = False
self.settings_tab.stopped = False
save_config("DestinationFolder" ,self.edit_destination_folder.get())
save_config("SteamCMDPath" ,self.edit_steamcmd_path.get())
@ -2051,6 +2166,13 @@ class BOIIIWD(ctk.CTk):
self.stop_download
return
if any(workshop_id in item for item in self.library_tab.added_items):
if self.settings_tab.skip_already_installed:
show_message("Heads up!, map skipped => Skip is on in settings", f"This item may already be installed, Stopping: {workshop_id}", icon="info")
self.stop_download
return
show_message("Heads up! map not skipped => Skip is off in settings", f"This item may already be installed: {workshop_id}", icon="info")
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)
@ -2058,17 +2180,14 @@ class BOIIIWD(ctk.CTk):
os.makedirs(download_folder)
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, steamcmd_reset
previous_net_speed = 0
est_downloaded_bytes = 0
start_time = time.time()
file_size = ws_file_size
while not stopped:
if steamcmd_reset:
steamcmd_reset = False
while not self.settings_tab.stopped:
if self.settings_tab.steamcmd_reset:
self.settings_tab.steamcmd_reset = False
previous_net_speed = 0
est_downloaded_bytes = 0
@ -2087,7 +2206,19 @@ class BOIIIWD(ctk.CTk):
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)}"))
if estimated_progress:
while not self.is_downloading:
self.after(1, self.label_speed.configure(text=f"Network Speed: 0 KB/s"))
time_elapsed = time.time() - start_time
elapsed_hours, elapsed_minutes, elapsed_seconds = convert_seconds(time_elapsed)
if self.settings_tab.show_fails:
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} - Fails: {self.settings_tab.steam_fail_counter}"))
else:
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)
if self.is_downloading:
break
if self.settings_tab.estimated_progress:
time_elapsed = time.time() - start_time
raw_net_speed = psutil.net_io_counters().bytes_recv
@ -2115,8 +2246,8 @@ class BOIIIWD(ctk.CTk):
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=min(percentage_complete ,99): self.progress_text.configure(text=f"{p:.2f}%"))
if show_fails:
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} - Fails: {steam_fail_counter}"))
if self.settings_tab.show_fails:
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} - Fails: {self.settings_tab.steam_fail_counter}"))
else:
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}"))
@ -2136,14 +2267,14 @@ class BOIIIWD(ctk.CTk):
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}%"))
if show_fails:
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} - Fails: {steam_fail_counter}"))
if self.settings_tab.show_fails:
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} - Fails: {self.settings_tab.steam_fail_counter}"))
else:
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))
command = f"+login anonymous app_update 311210 +workshop_download_item 311210 {workshop_id} validate +quit"
steamcmd_thread = threading.Thread(target=lambda: self.run_steamcmd_command(command, map_folder, workshop_id))
steamcmd_thread.start()
def wait_for_threads():
@ -2152,8 +2283,7 @@ class BOIIIWD(ctk.CTk):
update_ui_thread.start()
update_ui_thread.join()
global stopped
stopped = True
self.settings_tab.stopped = True
self.label_speed.configure(text="Network Speed: 0 KB/s")
self.progress_text.configure(text="0%")
@ -2185,11 +2315,11 @@ class BOIIIWD(ctk.CTk):
except Exception as E:
show_message("Error", f"Error copying files: {E}", icon="cancel")
if clean_on_finish:
if self.settings_tab.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")
msg = CTkMessagebox(title="Download Complete", message=f"{mod_type.capitalize()} files were downloaded\nYou can run the game now!\nPS: You have to restart the game \n(pressing launch will launch/restarts)", icon="info", option_1="Launch", option_2="Ok")
response = msg.get()
if response=="Launch":
launch_boiii_func(self.edit_destination_folder.get().strip())
@ -2206,17 +2336,16 @@ class BOIIIWD(ctk.CTk):
self.button_stop.configure(state="normal")
finally:
global steam_fail_counter
steam_fail_counter = 0
self.settings_tab.steam_fail_counter = 0
self.stop_download
self.is_pressed = False
def stop_download(self, on_close=None):
global stopped, steam_fail_counter
stopped = True
self.settings_tab.stopped = True
self.queue_stop_button = True
steam_fail_counter = 0
self.settings_tab.steam_fail_counter = 0
self.is_pressed = False
self.is_downloading = False
self.after(1, self.label_file_size.configure(text=f"File size: 0KB"))
if on_close:

BIN
dist/BOIIIWD.exe vendored

Binary file not shown.