Jul-27-2024, 09:44 PM
(This post was last modified: Jul-27-2024, 09:44 PM by LastStopDEVS.)
Hello, I was writing a script for a program to help me and my family on the computer with our RimWorld saves. We all share the computer and I am the only one who knows or has any scripting knowledge so I am trying to make a user friendly program that we can all use even the younger ones (12-14) and it be simple enough. So far everyone understands how to use the features from the first version. I have wrote a really nice second version but the file system isn't actually handling the appropriate actions. It doesn't move all the .RWS files to the folder appropriately but says that they have been moved..
Reddit Note: To Anyone coming here from Reddit to help, yes this is ASolidWorker and my script and code was not ripped from this post, it is my own work. Thank you.
Here is the script that functions properly that everyone is using currently.
Reddit Note: To Anyone coming here from Reddit to help, yes this is ASolidWorker and my script and code was not ripped from this post, it is my own work. Thank you.
Here is the script that functions properly that everyone is using currently.
import tkinter as tk from tkinter import ttk, messagebox, filedialog import os import shutil import json class GameSaveManagerApp: def __init__(self, root): self.root = root self.root.title("RWSG File Manager") self.current_folder = None self.save_root_folder = None self.file_structure = {} self.create_widgets() self.load_settings() def create_widgets(self): self.label_selected_folder = tk.Label(self.root, text="") self.label_selected_folder.pack() self.btn_open_folder = tk.Button(self.root, text="Open Folder", command=self.open_folder_dialog) self.btn_open_folder.pack() self.btn_move_saves = tk.Button(self.root, text="Move Saves to Folder", command=self.move_saves_to_folder) self.btn_move_saves.pack() self.btn_restore_files = tk.Button(self.root, text="Restore Files to Original Folders", command=self.restore_files_to_original_folders) self.btn_restore_files.pack() self.btn_cleanup_saves = tk.Button(self.root, text="Cleanup Saves", command=self.cleanup_saves) self.btn_cleanup_saves.pack() self.root.protocol("WM_DELETE_WINDOW", self.on_closing) def open_folder_dialog(self): folder_path = filedialog.askdirectory() if folder_path: self.current_folder = folder_path self.label_selected_folder.config(text=f"Selected Folder: {folder_path}") def move_saves_to_folder(self): if not self.save_root_folder: self.save_root_folder = filedialog.askdirectory(title="Select RimWorld Save Root Folder") if not self.save_root_folder: return self.save_settings() if not self.current_folder: messagebox.showwarning("Warning", "Please select a folder first.") return try: self.file_structure = {} for root, dirs, files in os.walk(self.current_folder): for file in files: source_path = os.path.join(root, file) destination_path = os.path.join(self.save_root_folder, file) if source_path != destination_path: shutil.move(source_path, destination_path) self.file_structure[file] = root self.save_settings() messagebox.showinfo("Success", "Files moved to RimWorld save folder successfully.") except Exception as e: messagebox.showerror("Error", f"Failed to move files: {str(e)}") def restore_files_to_original_folders(self): if not self.file_structure: messagebox.showwarning("Warning", "No file structure information available.") return try: for file, original_folder in self.file_structure.items(): source_path = os.path.join(self.save_root_folder, file) destination_path = os.path.join(original_folder, file) if source_path != destination_path: shutil.move(source_path, destination_path) messagebox.showinfo("Success", "Files restored to their original folders successfully.") except Exception as e: messagebox.showerror("Error", f"Failed to restore files: {str(e)}") def cleanup_saves(self): folder_path = filedialog.askdirectory(title="Select Folder to Cleanup") if not folder_path: return deleted_files = 0 try: for root, dirs, files in os.walk(folder_path): for file in files: if '#§#' in file: os.remove(os.path.join(root, file)) deleted_files += 1 messagebox.showinfo("Cleanup Complete", f"Deleted {deleted_files} files with '#§#' in the name.") except Exception as e: messagebox.showerror("Error", f"Failed to clean up saves: {str(e)}") def save_settings(self): settings = { 'current_folder': self.current_folder, 'save_root_folder': self.save_root_folder, 'file_structure': self.file_structure } with open('settings.json', 'w') as f: json.dump(settings, f) def load_settings(self): try: with open('settings.json', 'r') as f: settings = json.load(f) self.current_folder = settings.get('current_folder') self.save_root_folder = settings.get('save_root_folder') self.file_structure = settings.get('file_structure', {}) if self.current_folder: self.label_selected_folder.config(text=f"Selected Folder: {self.current_folder}") except FileNotFoundError: pass def on_closing(self): self.save_settings() self.root.destroy() if __name__ == "__main__": root = tk.Tk() app = GameSaveManagerApp(root) root.mainloop()Here is the updated python script that I am having problems with and is not properly doing the actual moving of the files but the interface seems to function properly.. I was working on this really late and probably got sleepy, I have looked over it today and just can't seem to find the problem.. Maybe fresh eyes will help. Thank you to anyone willing to take their personal time to help me with our crazy RimWorld nonsense xP
import tkinter as tk from tkinter import ttk, messagebox, filedialog import os import shutil import json class GameSaveManagerApp: def __init__(self, root): self.root = root self.root.title("RWSG File Manager") self.root.geometry("600x210") self.root.resizable(False, False) # Make the window non-resizable self.personal_saves_folder = None self.save_root_folder = None self.file_structure = {} self.move_completed = False self.pop_up_dsaves = False self.pop_up_psaves = False self.create_widgets() self.load_settings() self.update_button_states() # Initialize button states based on settings def create_widgets(self): self.label_selected_folder = tk.Label(self.root, text="") self.label_selected_folder.pack() self.btn_select_folder = tk.Button(self.root, text="Select Your Folder", command=self.open_folder_dialog) self.btn_select_folder.pack() self.create_tooltip(self.btn_select_folder, "This is where you select the personal folder of the user who is going to play this session. This is the folder you keep your .RWS saved games in while anyone other than you is playing. You can have multiple folders inside your personal folder and the program will keep track of this and remember the place of all your saves and keep its organization when they get moved back.") self.btn_move_saves = tk.Button(self.root, text="Move .RWS Files", command=self.move_saves_to_folder, state=tk.DISABLED) self.btn_move_saves.pack() self.create_tooltip(self.btn_move_saves, "Move any .RWS files from inside the personal folder selected and all of its sub-directories to the default RimWorld Saves Folder you selected.") self.btn_restore_files = tk.Button(self.root, text="Restore .RWS Files", command=self.restore_files_to_original_folders, state=tk.DISABLED) self.btn_restore_files.pack() self.btn_cleanup_saves = tk.Button(self.root, text="Cleanup Saves", command=self.cleanup_saves) self.btn_cleanup_saves.pack() self.tooltip_label = tk.Label(self.root, text="", wraplength=580, justify=tk.LEFT) self.tooltip_label.pack(side=tk.BOTTOM, fill=tk.X, padx=10, pady=10) self.root.protocol("WM_DELETE_WINDOW", self.on_closing) def create_tooltip(self, widget, text): def enter(event): self.tooltip_label.config(text=text) def leave(event): self.tooltip_label.config(text="") widget.bind("<Enter>", enter) widget.bind("<Leave>", leave) def open_folder_dialog(self): if not self.pop_up_dsaves: messagebox.showinfo("Select Folder", "Please find the default saves folder. This is the folder that the save game files are saved to by default when you save a game inside of RimWorld.") self.save_root_folder = filedialog.askdirectory(title="Find Your Default RimWorld Save Folder") self.pop_up_dsaves = True self.save_settings() if not self.save_root_folder: self.pop_up_dsaves = False # Reset if user cancels return if not self.pop_up_psaves: messagebox.showinfo("Select Folder", "Please find your personal saves folder. This is the folder that you keep all of your .RWS files in when a friend or family member is playing RimWorld. It can contain many other folders inside of it for example. In the RimWorld Saves default directory you could have your own folders inside named whatever you want i.e: 'User 1', 'User 2' and within those folders you can have all of your personal game saves for each user and they can each be organized however the user wants. The program remembers this information within the settings file. If something ever goes wrong make sure all .RWS files are back in their own personal folders making sure the Default Save folder is empty. Then delete the settings file and run the program again as if it is running for the first time. Now, please select your personal saves folder.") self.personal_saves_folder = filedialog.askdirectory(title="Select Your Personal Saves Folder") self.pop_up_psaves = True self.save_settings() if not self.personal_saves_folder: self.pop_up_psaves = False # Reset if user cancels return if self.personal_saves_folder: self.label_selected_folder.config(text=f"Selected Folder: {self.personal_saves_folder}") self.update_button_states() def move_saves_to_folder(self): if not self.personal_saves_folder or not self.save_root_folder: messagebox.showwarning("Warning", "Please select the personal folder and RimWorld saves folder first.") return try: self.file_structure = {} for root, dirs, files in os.walk(self.personal_saves_folder): for file in files: if file.endswith(".RWS"): source_path = os.path.join(root, file) destination_path = os.path.join(self.save_root_folder, file) if source_path != destination_path: shutil.move(source_path, destination_path) self.file_structure[file] = root print(f"Moved: {source_path} to {destination_path}") # Debugging statement self.move_completed = True self.save_settings() self.update_button_states() messagebox.showinfo("Success", "Files moved to RimWorld save folder successfully.") except Exception as e: messagebox.showerror("Error", f"Failed to move files: {str(e)}") def restore_files_to_original_folders(self): if not self.file_structure: messagebox.showwarning("Warning", "No file structure information available.") return try: for file, original_folder in self.file_structure.items(): source_path = os.path.join(self.save_root_folder, file) destination_path = os.path.join(original_folder, file) if source_path != destination_path: shutil.move(source_path, destination_path) print(f"Restored: {source_path} to {destination_path}") # Debugging statement self.move_completed = False self.save_settings() self.update_button_states() messagebox.showinfo("Success", "Files restored to their original folders successfully.") except Exception as e: messagebox.showerror("Error", f"Failed to restore files: {str(e)}") def cleanup_saves(self): folder_path = filedialog.askdirectory(title="Select Folder to Cleanup") if not folder_path: return deleted_files = 0 try: for root, dirs, files in os.walk(folder_path): for file in files: if '#§#' in file: os.remove(os.path.join(root, file)) deleted_files += 1 messagebox.showinfo("Cleanup Complete", f"Deleted {deleted_files} files with '#§#' in the name.") except Exception as e: messagebox.showerror("Error", f"Failed to clean up saves: {str(e)}") def update_button_states(self): if self.pop_up_dsaves and self.pop_up_psaves and self.personal_saves_folder: self.btn_move_saves.config(state=tk.NORMAL) else: self.btn_move_saves.config(state=tk.DISABLED) if self.move_completed: self.btn_move_saves.config(state=tk.DISABLED) self.btn_restore_files.config(state=tk.NORMAL) self.btn_select_folder.config(state=tk.DISABLED) else: self.btn_restore_files.config(state=tk.DISABLED) self.btn_select_folder.config(state=tk.NORMAL) self.save_settings() def save_settings(self): settings = { 'personal_saves_folder': self.personal_saves_folder, 'save_root_folder': self.save_root_folder, 'file_structure': self.file_structure, 'move_completed': self.move_completed, 'pop_up_dsaves': self.pop_up_dsaves, 'pop_up_psaves': self.pop_up_psaves } with open('settings.json', 'w') as f: json.dump(settings, f) def load_settings(self): try: with open('settings.json', 'r') as f: settings = json.load(f) self.personal_saves_folder = settings.get('personal_saves_folder') self.save_root_folder = settings.get('save_root_folder') self.file_structure = settings.get('file_structure', {}) self.move_completed = settings.get('move_completed', False) self.pop_up_dsaves = settings.get('pop_up_dsaves', False) self.pop_up_psaves = settings.get('pop_up_psaves', False) if self.personal_saves_folder: self.label_selected_folder.config(text=f"Selected Folder: {self.personal_saves_folder}") self.update_button_states() except FileNotFoundError: pass def on_closing(self): self.save_settings() self.root.destroy() if __name__ == "__main__": root = tk.Tk() app = GameSaveManagerApp(root) root.mainloop()Run both scripts to get an idea of what has changed between the interface. Also if you have RimWorld on your computer you can just run the software and bug test it yourself if you have coding knowledge and want to see what is up and how it works yourself. Besides that, if you make your own files with the .RWS extension then you can just select your own two folders for the software and it will work the same way for a coder testing it on their computer in a test environment without RimWorld being on the computer.. Just take a notepad file and save it as, change from text-document to all files and save it as file_name.rws and it will allow the program to function for you as if the files are RimWorld Saves and you can see how the program functions yourself.