Skip to content
This repository was archived by the owner on Aug 26, 2022. It is now read-only.

Commit 8b113f9

Browse files
v0.10 (added fullscreen)
1 parent 48db6d8 commit 8b113f9

File tree

3 files changed

+115
-73
lines changed

3 files changed

+115
-73
lines changed

APLauncher.pyw

Lines changed: 74 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from tkinter import *
22
from tkinter.ttk import *
33
from tkinter.scrolledtext import ScrolledText
4-
from tkinter import messagebox, filedialog
4+
from tkinter import messagebox, filedialog, Canvas
55
from PIL import ImageTk, Image
66
from urllib.request import urlretrieve
77
from urllib.error import *
@@ -28,7 +28,7 @@ import socket
2828
import random
2929
import platform
3030

31-
VERSION = "0.9"
31+
VERSION = "0.10"
3232

3333
def send_error_report(prog, fatal=False):
3434
try:
@@ -100,22 +100,28 @@ class App:
100100
logger.info("AP Launcher has started, now initalizing window.")
101101
self.win = Tk()
102102
self.win.title(f"AP Launcher v{VERSION}")
103+
self.win.rowconfigure(0, weight=1)
104+
self.win.columnconfigure(0, weight=1)
103105
self.tabs = Notebook(self.win)
104-
self.tabs.grid()
106+
self.tabs.grid(column=0, row=0, sticky="nsew")
107+
self.tabs.rowconfigure(0, weight=1)
108+
self.tabs.columnconfigure(0, weight=1)
105109
self.minecraftdir = os.path.join(os.getenv('APPDATA'), '.minecraft')
106110
self.win.protocol("WM_DESTROY_WINDOW", lambda: self.on_closing())
107111
self.win.protocol("WM_DELETE_WINDOW", lambda: self.on_closing())
108112
self.accounts = self.get_accounts()
109113
self.mainframe = Frame(self.win)
114+
self.mainframe.rowconfigure(0, weight=1)
115+
self.mainframe.columnconfigure(0, weight=1)
110116
self.tabs.add(self.mainframe, text="Versions", sticky="nsew")
111117
logger.info("Cleaning up any leftover update files...")
112118
if not os.path.isdir("assets"):
113119
os.mkdir("assets")
114120
if not os.path.isdir("temp"):
115121
os.mkdir("temp")
116122
try:
117-
os.remove("temp/APLauncher.exe")
118-
os.remove("temp/launcher_process.exe")
123+
os.remove("APLauncher_old.exe")
124+
os.remove("launcher_process_old.exe")
119125
logger.info("Update files cleaned up.")
120126
except:
121127
logger.info("No update files found")
@@ -131,11 +137,13 @@ class App:
131137
except URLError:
132138
logger.info("Unable to retrieve background and icon, using cached.")
133139
pass
134-
self.background = ImageTk.PhotoImage(Image.open("assets/background.png"))
140+
self.background = ImageTk.PhotoImage(file="assets/background.png")
141+
self.win.geometry(f"{self.background.width()}x{self.background.height()}")
135142
self.icon = ImageTk.PhotoImage(file="assets/icon.ico")
136143
self.win.iconphoto(True, self.icon)
137-
self.background2 = Label(self.mainframe, image=self.background)
144+
self.background2 = Canvas(self.mainframe, width=self.background.width(), height=self.background.height())
138145
self.background2.grid(column=0, row=0, sticky="nsew")
146+
self.win.bind("<Configure>", lambda e: threading.Thread(None, target=lambda: self.resize_widgets(e)).start())
139147
self.versionvar = StringVar()
140148
self.get_versions()
141149
logger.info("Reading cache file...")
@@ -196,10 +204,13 @@ class App:
196204
self.playcontext.entryconfigure(0, state="disabled")
197205
self.playbutton.bind("<Button-3>", lambda x: self.do_popup(x))
198206
self.processframe = Frame(self.win)
199-
self.tabs.add(self.processframe, text="Game Output")
200-
self.processtext = ScrolledText(self.processframe, state="disabled", height=35, width=120)
201-
self.processtext.grid(column=0, row=2, sticky="nsew")
207+
self.processframe.rowconfigure(0, weight=1)
208+
self.processframe.columnconfigure(0, weight=1)
209+
self.tabs.add(self.processframe, text="Game Output", sticky="nsew")
210+
self.processtext = ScrolledText(self.processframe, state="disabled")
211+
self.processtext.grid(column=0, row=0, sticky="nsew")
202212
self.profileframe = Frame(self.win)
213+
self.profileframe.columnconfigure(0, weight=1)
203214
self.tabs.add(self.profileframe, text="Profiles")
204215
self.profileselect = Frame(self.profileframe)
205216
self.profileselect.grid(column=0, row=0, sticky="nsew")
@@ -211,7 +222,7 @@ class App:
211222
try:
212223
self.profname = LabeledEntry(self.profileframe, "Name: ", self.accounts["profiles"][self.nametoprofile[self.versionvar.get()]]["name"])
213224
except KeyError:
214-
self.profname = LabeledEntry(self.profileframe, "Name: ", "N/A")
225+
self.profname = LabeledEntry(self.profileframe, "Name: ", "")
215226
self.profname.grid(column=0, row=1, sticky="nsew")
216227
self.profgamedir = LabeledEntry(self.profileframe, "Game Directory: ", os.path.join(os.getenv('APPDATA'), '.minecraft'), elength=30)
217228
self.profgamedir.grid(column=0, row=2, sticky="nsew")
@@ -225,31 +236,29 @@ class App:
225236
self.profjavargs = LabeledEntry(self.profileframe, "JVM Arguments: ", "-Xmx2G -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M", elength=50)
226237
self.profjavargs.grid(column=0, row=4, sticky="nsew")
227238
self.profsave = Button(self.profileframe, text="Save")
228-
self.profsave.grid(column=0, row=5, sticky="nsew")
239+
self.profsave.grid(column=0, row=5, sticky="w")
229240
self.proftrans = Label(self.profileframe, text="OR")
230-
self.proftrans.grid(column=0, row=6, sticky="nsew")
241+
self.proftrans.grid(column=0, row=6, sticky="w")
231242
self.profadd = Button(self.profileframe, text="Import new version", command=lambda: self.open_install_archive())
232-
self.profadd.grid(column=0, row=7, sticky="nsew")
243+
self.profadd.grid(column=0, row=7, sticky="w")
233244
self.update_profiles(self.versionvar.get())
234245
self.profilelist.bind("<<ComboboxSelected>>", lambda x: self.update_profiles(self.versionvar.get()))
235246
self.aboutpage = AboutPage(self.win)
247+
self.aboutpage.columnconfigure(0, weight=1)
236248
self.tabs.add(self.aboutpage, text="About")
237249
logger.info("Successfully initiated window.")
238250

251+
def resize_widgets(self, e, override=False):
252+
if ((self.win.winfo_width() != e.width) and (self.win.winfo_height() != e.height)) or override:
253+
self.bgfile = Image.open("assets/background.png")
254+
self.bgfile = self.bgfile.resize((e.width, e.height), Image.ANTIALIAS)
255+
self.background = ImageTk.PhotoImage(self.bgfile)
256+
self.background2.create_image(0, 0, image=self.background, anchor="nw")
257+
239258
def kill_process(self):
240-
"""Kills the running Minecraft process. I dont really know what to do about this function..."""
241-
try:
242-
temp = open("temp.txt")
243-
except FileNotFoundError:
244-
messagebox.showerror("Error", "Unable to stop the process because the process id was not loaded.")
245-
return
246-
try:
247-
pid = int(temp.read())
248-
except:
249-
messagebox.showerror("Error", "Unable to stop the process because the process id was corrupted.")
250-
return
259+
"""Kills the running Minecraft process."""
251260
try:
252-
os.system(f"taskkill /pid {pid} /f")
261+
os.system(f'taskkill /FI "WindowTitle eq Minecraft*" /T /F')
253262
except:
254263
messagebox.showerror("Error", "Unable to stop the process.")
255264
return
@@ -269,9 +278,7 @@ class App:
269278
json.dump(self.accounts, open(os.path.join(self.minecraftdir, "launcher_profiles.json"), "w"), indent=2)
270279
json.dump(self.cache, open("cache.json", "w"), indent=2)
271280
self.win.withdraw()
272-
if self.update_version():
273-
logger.info("Update is required, setting up asynchronous update process.")
274-
atexit.register(lambda: self.run_updater())
281+
self.update_version()
275282
sys.exit()
276283

277284
def get_versions(self):
@@ -423,7 +430,7 @@ class App:
423430
def update_procscreen(self, text):
424431
"""Updates the console screen"""
425432
self.processtext.config(state="normal")
426-
self.processtext.insert("end", text+"\n")
433+
self.processtext.insert("end", text)
427434
self.processtext.config(state="disabled")
428435
self.processtext.see("end")
429436

@@ -438,9 +445,9 @@ class App:
438445
def get_latest_version(self, type_):
439446
versions = [x[0] for x in os.walk(os.path.join(self.minecraftdir, "versions"))]
440447
if type_ == "release":
441-
filtered = [x.split("\\")[-1][:6] for x in versions if bool(re.match("1\.[0-9]+\.[1-9]+", x.split("\\")[-1])) or bool(re.match("1\.[0-9]+", x.split("\\")[-1]))]
448+
filtered = [x.split("\\")[-1][:6] for x in versions if bool(re.match(r"1\.[0-9]+\.[1-9]+", x.split("\\")[-1])) or bool(re.match(r"1\.[0-9]+", x.split("\\")[-1]))]
442449
for x in range(len(filtered)):
443-
if bool(re.match("1\.[0-9]+", filtered[x])):
450+
if bool(re.match(r"1\.[0-9]+", filtered[x])):
444451
filtered[x] += ".0"
445452
ranked = [int(x.replace(".", "")) for x in filtered]
446453
if filtered[ranked.index(max(ranked))].endswith(".0"):
@@ -465,8 +472,22 @@ class App:
465472
return
466473
with ZipFile(open(filepath, "rb")) as zf:
467474
folders = list(set([os.path.dirname(x).split("/")[0] for x in zf.namelist()]))
468-
folders.remove("indexes")
469-
folders.remove("natives")
475+
try:
476+
folders.remove("indexes")
477+
except ValueError:
478+
pass
479+
try:
480+
folders.remove("natives")
481+
except ValueError:
482+
pass
483+
try:
484+
folders.remove("libraries")
485+
except ValueError:
486+
pass
487+
try:
488+
folders.remove("objects")
489+
except ValueError:
490+
pass
470491
folders.remove("")
471492
infofile = zf.open("manifest.json")
472493
info = json.load(infofile)
@@ -484,14 +505,23 @@ class App:
484505
zf.extract(file_, os.path.join(self.minecraftdir, "versions"))
485506
info["profile"][list(info["profile"].keys())[0]]["created"] = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z"
486507
self.accounts["profiles"][list(info["profile"].keys())[0]] = info["profile"][list(info["profile"].keys())[0]]
487-
logger.info("Extracting asset indexes...")
508+
logger.info("Extracting assets...")
488509
for file_ in zf.namelist():
489510
if file_.startswith("indexes"):
490511
zf.extract(file_, os.path.join(self.minecraftdir, "assets"))
512+
for file_ in zf.namelist():
513+
if file_.startswith("objects"):
514+
zf.extract(file_, os.path.join(self.minecraftdir, "assets"))
491515
logger.info("Extracting required DLL files...")
492516
for file_ in zf.namelist():
493517
if file_.startswith("natives"):
494518
zf.extract(file_, os.path.join(self.minecraftdir, "bin"))
519+
logger.info("Extracting libraries...")
520+
for file_ in zf.namelist():
521+
if file_.startswith("libraries"):
522+
if not os.path.isdir(os.path.join(self.minecraftdir, *file_.split("/")[:-1])):
523+
os.makedirs(os.path.join(self.minecraftdir, *file_.split("/")[:-1]), exist_ok=True)
524+
zf.extract(file_, self.minecraftdir)
495525
messagebox.showinfo("Success", "The version was successfully imported. Restart AP Launcher to see changes.")
496526
zf.close()
497527
return
@@ -512,7 +542,7 @@ class App:
512542
durl = asset["browser_download_url"]
513543
break
514544
if durl is None:
515-
return False
545+
return
516546
if not os.path.isdir("update"):
517547
os.mkdir("update")
518548
urlretrieve(url=durl, filename="update/update.zip")
@@ -532,20 +562,16 @@ class App:
532562
f2.close()
533563
if hash1.hexdigest() != hash2.hexdigest():
534564
logger.info("Update found.")
535-
return True
536-
return False
537-
else:
538-
return False
539-
540-
def run_updater(self):
541-
if os.path.isfile("APLauncher.exe"):
542-
shutil.move("APLauncher.exe", "temp/APLauncher.exe")
543-
if os.path.isfile("launcher_process.exe"):
544-
shutil.move("launcher_process.exe", "temp/launcher_process.exe")
545-
shutil.move("update/APLauncher.exe", "APLauncher.exe")
546-
shutil.move("update/launcher_process.exe", "launcher_process.exe")
565+
if os.path.isfile("APLauncher.exe"):
566+
os.rename("APLauncher.exe", "APLauncher_old.exe")
567+
if os.path.isfile("launcher_process.exe"):
568+
os.rename("launcher_process.exe", "launcher_process_old.exe")
569+
shutil.move("update/APLauncher.exe", "APLauncher.exe")
570+
shutil.move("update/launcher_process.exe", "launcher_process.exe")
547571

548572
if __name__ == "__main__":
573+
if not os.path.isdir("launcher_logs"):
574+
os.mkdir("launcher_logs")
549575
if not os.path.isdir("launcher_logs/gui"):
550576
os.mkdir("launcher_logs/gui")
551577
if os.path.isfile("launcher_logs/gui/latest.log"):

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ You may need to install some libraries, including...
1313
* Premium accounts are NOT supported.
1414

1515
# Changelog:
16-
* Added mod support. (please tell me if one doesn't work)
17-
* Added logging.
18-
* AP Launcher now tells you when it crashes, and it allows you to report those crashes on Github.
16+
* Fullscreen now added (may be buggy)
17+
* Fixed the updater (probably still broken...)
18+
* Updated version file format
19+
* Re-added the ability to kill the Minecraft process
1920

2021
# Installation instructions:
2122

0 commit comments

Comments
 (0)