1+ import os
2+ import json
3+
4+ def get_current_mod_name (current_dir ):
5+ json_path = os .path .join (current_dir , "dev-data" , "datamain.json" )
6+ if os .path .exists (json_path ):
7+ try :
8+ with open (json_path , 'r' , encoding = 'utf-8' ) as f :
9+ data = json .load (f )
10+ return data .get ("mod_name" , "My Mod" ).strip ()
11+ except Exception :
12+ pass
13+ return "My Mod"
14+
15+ def update_json_file (current_dir , clean_name ):
16+ json_dir = os .path .join (current_dir , "dev-data" )
17+ json_path = os .path .join (json_dir , "datamain.json" )
18+ if not os .path .exists (json_dir ):
19+ os .makedirs (json_dir )
20+ try :
21+ if os .path .exists (json_path ):
22+ with open (json_path , 'r' , encoding = 'utf-8' ) as f :
23+ data = json .load (f )
24+ else :
25+ data = {}
26+ except Exception :
27+ data = {}
28+
29+ data ["mod_name" ] = clean_name
30+ try :
31+ with open (json_path , 'w' , encoding = 'utf-8' ) as f :
32+ json .dump (data , f , indent = 4 )
33+ print (f"[2/2] Updated JSON config to: '{ clean_name } '" )
34+ return True
35+ except Exception as e :
36+ print (f"[!] Error writing to JSON file: { e } " )
37+ return False
38+
39+ def rename_mod (mod_name ):
40+ clean_name = mod_name .strip ()
41+ if not clean_name :
42+ print ("Error: Mod name cannot be empty." )
43+ return
44+
45+ try :
46+ current_dir = os .path .dirname (os .path .abspath (__file__ ))
47+ current_target_name = get_current_mod_name (current_dir )
48+
49+ items = os .listdir (current_dir )
50+ old_folder_path = None
51+ normalized_target = "" .join (current_target_name .split ()).lower ()
52+
53+ for item in items :
54+ item_path = os .path .join (current_dir , item )
55+ if os .path .isdir (item_path ):
56+ if "" .join (item .split ()).lower () == normalized_target :
57+ old_folder_path = item_path
58+ break
59+
60+ if not old_folder_path :
61+ old_folder_path = os .path .join (current_dir , current_target_name )
62+
63+ if not os .path .exists (old_folder_path ) and normalized_target != "mymod" :
64+ for item in items :
65+ if "" .join (item .split ()).lower () == "mymod" :
66+ old_folder_path = os .path .join (current_dir , item )
67+ break
68+
69+ if not os .path .exists (old_folder_path ):
70+ print (f"\n Error: Could not find your mod folder anywhere." )
71+ return
72+
73+ new_folder_path = os .path .join (current_dir , clean_name )
74+ print (f"[1/2] Renaming folder to: { clean_name } ..." )
75+ os .rename (old_folder_path , new_folder_path )
76+ update_json_file (current_dir , clean_name )
77+ print ("----------------------------------------" )
78+ print ("Mod track and rename updated successfully!" )
79+ print ("----------------------------------------" )
80+
81+ except Exception as e :
82+ print (f"Error handling mod update: { e } " )
83+
84+ def package_mod ():
85+ import shutil
86+ try :
87+ current_dir = os .path .dirname (os .path .abspath (__file__ ))
88+ current_mod = get_current_mod_name (current_dir )
89+ mod_folder_path = os .path .join (current_dir , current_mod )
90+
91+ if not os .path .exists (mod_folder_path ):
92+ print (f"[!] Error: Active mod folder '{ current_mod } ' not found to package." )
93+ return
94+
95+ zips_dir = os .path .join (current_dir , "Zips" )
96+ if not os .path .exists (zips_dir ):
97+ os .makedirs (zips_dir )
98+
99+ for root , dirs , files in os .walk (mod_folder_path ):
100+ if "__pycache__" in dirs :
101+ shutil .rmtree (os .path .join (root , "__pycache__" ))
102+
103+ print (f"[1/2] Packaging mod folder '{ current_mod } '..." )
104+ zip_output_base = os .path .join (zips_dir , current_mod )
105+
106+ shutil .make_archive (zip_output_base , 'zip' , current_dir , current_mod )
107+
108+ print (f"[2/2] Saved clean distribution package to: Zips/{ current_mod } .zip" )
109+ print ("----------------------------------------" )
110+ print ("Mod packaged and exported successfully!" )
111+ print ("----------------------------------------" )
112+
113+ except Exception as e :
114+ print (f"Error while packaging mod: { e } " )
115+
116+ def load_template_command ():
117+ try :
118+ current_dir = os .path .dirname (os .path .abspath (__file__ ))
119+ current_mod = get_current_mod_name (current_dir )
120+ mod_folder_path = os .path .join (current_dir , current_mod )
121+
122+ if not os .path .exists (mod_folder_path ):
123+ print (f"[!] Error: Active mod folder '{ current_mod } ' not found. Name a mod first!" )
124+ return
125+
126+ init_path = os .path .join (mod_folder_path , "__init__.py" )
127+
128+ init_code = '''import os
129+ import platform
130+
131+ def say_works_sir():
132+ message = "Works, sir."
133+ print(f"SOAR: {message}")
134+
135+ current_os = platform.system()
136+ if current_os == "Darwin":
137+ os.system(f"say -v Daniel '{message}'")
138+ else:
139+ try:
140+ import pyttsx3
141+ engine = pyttsx3.init()
142+ engine.say(message)
143+ engine.runAndWait()
144+ except Exception:
145+ pass
146+
147+ MOD_COMMANDS = {
148+ "test": say_works_sir
149+ }
150+
151+ def initialize_addon():
152+ pass
153+ '''
154+ with open (init_path , "w" , encoding = "utf-8" ) as f :
155+ f .write (init_code )
156+ print (f" -> Created compliant command template in { current_mod } /__init__.py" )
157+ print ("\n ----------------------------------------" )
158+ print ("Success! Template generated for Public Edition compatibility." )
159+ print ("----------------------------------------" )
160+
161+ except Exception as e :
162+ print (f"Error creating template command: { e } " )
163+
164+ def load_template_window ():
165+ try :
166+ current_dir = os .path .dirname (os .path .abspath (__file__ ))
167+ current_mod = get_current_mod_name (current_dir )
168+ mod_folder_path = os .path .join (current_dir , current_mod )
169+
170+ if not os .path .exists (mod_folder_path ):
171+ print (f"[!] Error: Active mod folder '{ current_mod } ' not found. Name a mod first!" )
172+ return
173+
174+ init_path = os .path .join (mod_folder_path , "__init__.py" )
175+
176+ init_code = '''import tkinter as tk
177+ import threading
178+
179+ def launch_gui():
180+ root = tk.Tk()
181+ root.title("SOAR Mod Window")
182+ root.geometry("300x150")
183+
184+ label = tk.Label(root, text="Mod Interface Running!", font=("Arial", 14))
185+ label.pack(pady=20)
186+
187+ btn = tk.Button(root, text="Close", command=root.destroy)
188+ btn.pack(pady=10)
189+
190+ root.mainloop()
191+
192+ MOD_COMMANDS = {}
193+
194+ def initialize_addon():
195+ gui_thread = threading.Thread(target=launch_gui, daemon=True)
196+ gui_thread.start()
197+ '''
198+ with open (init_path , "w" , encoding = "utf-8" ) as f :
199+ f .write (init_code )
200+ print (f" -> Created cross-platform GUI window template in { current_mod } /__init__.py" )
201+ print ("\n ----------------------------------------" )
202+ print ("Success! Window addon template generated." )
203+ print ("----------------------------------------" )
204+
205+ except Exception as e :
206+ print (f"Error creating template window: { e } " )
207+
208+ def load_template_addon ():
209+ try :
210+ current_dir = os .path .dirname (os .path .abspath (__file__ ))
211+ current_mod = get_current_mod_name (current_dir )
212+ mod_folder_path = os .path .join (current_dir , current_mod )
213+
214+ if not os .path .exists (mod_folder_path ):
215+ print (f"[!] Error: Active mod folder '{ current_mod } ' not found. Name a mod first!" )
216+ return
217+
218+ init_path = os .path .join (mod_folder_path , "__init__.py" )
219+
220+ init_code = '''import os
221+ import platform
222+ import threading
223+ import time
224+
225+ def background_loop():
226+ message = "My Bot Mod Running..."
227+ current_os = platform.system()
228+
229+ while True:
230+ time.sleep(10)
231+ print(f"SOAR: {message}")
232+
233+ if current_os == "Darwin":
234+ os.system(f"say -v Daniel '{message}'")
235+ else:
236+ try:
237+ import pyttsx3
238+ engine = pyttsx3.init()
239+ engine.say(message)
240+ engine.runAndWait()
241+ except Exception:
242+ pass
243+
244+ MOD_COMMANDS = {}
245+
246+ def initialize_addon():
247+ bg_thread = threading.Thread(target=background_loop, daemon=True)
248+ bg_thread.start()
249+ '''
250+ with open (init_path , "w" , encoding = "utf-8" ) as f :
251+ f .write (init_code )
252+ print (f" -> Created background loop addon template in { current_mod } /__init__.py" )
253+ print ("\n ----------------------------------------" )
254+ print ("Success! Background loop addon template generated." )
255+ print ("----------------------------------------" )
256+
257+ except Exception as e :
258+ print (f"Error creating template addon: { e } " )
259+
260+ def create_config ():
261+ try :
262+ current_dir = os .path .dirname (os .path .abspath (__file__ ))
263+ current_mod = get_current_mod_name (current_dir )
264+ mod_folder_path = os .path .join (current_dir , current_mod )
265+
266+ if not os .path .exists (mod_folder_path ):
267+ print (f"[!] Error: Active mod folder '{ current_mod } ' not found. Name a mod first!" )
268+ return
269+
270+ config_path = os .path .join (mod_folder_path , "config.json" )
271+ default_config = {
272+ "mywordvariable" : "Hello World" ,
273+ "mynumbervariable" : 1 ,
274+ "myfalsetruevariable" : True ,
275+ }
276+
277+ with open (config_path , "w" , encoding = "utf-8" ) as f :
278+ json .dump (default_config , f , indent = 4 )
279+ print (f" -> Created default configuration at { current_mod } /config.json" )
280+
281+ init_path = os .path .join (mod_folder_path , "__init__.py" )
282+ init_code = '''import os
283+ import json
284+ import platform
285+
286+ def load_mod_config():
287+ current_dir = os.path.dirname(os.path.abspath(__file__))
288+ config_path = os.path.join(current_dir, "config.json")
289+ if os.path.exists(config_path):
290+ try:
291+ with open(config_path, "r", encoding="utf-8") as f:
292+ return json.load(f)
293+ except Exception:
294+ pass
295+ return {}
296+
297+ def say_works_sir():
298+ config = load_mod_config()
299+ message = config.get("custom_alert_message", "Works, sir.")
300+ bot_name = config.get("bot_name", "SOAR")
301+
302+ print(f"{bot_name}: {message}")
303+
304+ if config.get("voice_enabled", True):
305+ current_os = platform.system()
306+ if current_os == "Darwin":
307+ os.system(f"say -v Daniel '{message}'")
308+ else:
309+ try:
310+ import pyttsx3
311+ engine = pyttsx3.init()
312+ engine.say(message)
313+ engine.runAndWait()
314+ except Exception:
315+ pass
316+
317+ MOD_COMMANDS = {
318+ "test": say_works_sir
319+ }
320+
321+ def initialize_addon():
322+ pass
323+ '''
324+ with open (init_path , "w" , encoding = "utf-8" ) as f :
325+ f .write (init_code )
326+ print (f" -> Injected JSON config reader routine into { current_mod } /__init__.py" )
327+ print ("\n ----------------------------------------" )
328+ print ("Success! Configuration management system initialized." )
329+ print ("----------------------------------------" )
330+
331+ except Exception as e :
332+ print (f"Error creating config generator: { e } " )
333+
334+ def main ():
335+ print ("====================================" )
336+ print ("Soar Developer Mod Creation Tool" )
337+ print ("Commands:" )
338+ print (" - Name mod <name> (Renames active folder & config)" )
339+ print (" - template load command (Generates cross-platform TTS command)" )
340+ print (" - template load addon (Generates 10s background loop bot)" )
341+ print (" - mod package (Creates a distributable zip file of the active mod)" )
342+ print (" - create config (Generates managed JSON configurations)" )
343+ print (" - template load window (Generates cross-platform GUI window)" )
344+ print (" - exit (Close)" )
345+ print ("====================================" )
346+
347+ while True :
348+ try :
349+ user_input = input ("\n Enter command: " ).strip ()
350+
351+ if user_input .lower () == 'exit' :
352+ print ("Exiting developer tool." )
353+ break
354+ elif user_input .lower () == "template load command" :
355+ load_template_command ()
356+ elif user_input .lower () == "template load addon" :
357+ load_template_addon ()
358+ elif user_input .lower () == "template load window" :
359+ load_template_window ()
360+ elif user_input .lower () == "mod package" :
361+ package_mod ()
362+ elif user_input .lower () == "create config" :
363+ create_config ()
364+ elif user_input .lower ().startswith ("name mod " ):
365+ target_name = user_input [9 :]
366+ rename_mod (target_name )
367+ else :
368+ print ("Invalid command syntax." )
369+
370+ except (KeyboardInterrupt , EOFError ):
371+ print ("\n Exiting developer tool." )
372+ break
373+
374+ if __name__ == "__main__" :
375+ main ()
0 commit comments