Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 1.0.3 #8

Merged
merged 73 commits into from
Nov 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
dd51440
added some features and change some other stuff
urwrstkn8mare Jul 18, 2020
44ae78d
minor restructuring + removed more-galaxy-utils and just moved the ne…
urwrstkn8mare Jul 18, 2020
179b069
updated readme
urwrstkn8mare Jul 18, 2020
cd11a6d
add doubleclick decorator
urwrstkn8mare Jul 21, 2020
855b5c4
add .DS_Store to .gitignore
urwrstkn8mare Jul 21, 2020
ebf6e68
add source to jquery.imgcheckbox.js
urwrstkn8mare Jul 21, 2020
58c916d
updated source for styles.css + fonts
urwrstkn8mare Jul 21, 2020
92c164f
added support for MultiMC + small things
urwrstkn8mare Jul 22, 2020
8ed9fc0
miniscule update to decorators.py top comment
urwrstkn8mare Jul 22, 2020
cc8997b
update readme credits
urwrstkn8mare Jul 22, 2020
08b3209
removed psutils requirement and got game running status from Popen re…
urwrstkn8mare Jul 23, 2020
0c235d1
tested for mac and made some fixes
urwrstkn8mare Jul 23, 2020
8c27acb
update build.py
urwrstkn8mare Jul 25, 2020
261825e
update build.py
urwrstkn8mare Jul 25, 2020
7c33179
fixed issue where user is prompted everytime he/she launches gog gala…
urwrstkn8mare Jul 28, 2020
59fbaa9
fixed multimcpath not saving after gog galaxy shutdown
urwrstkn8mare Jul 29, 2020
c34f546
update build section in readme
urwrstkn8mare Jul 29, 2020
e01cbaa
Merge pull request #7 from urwrstkn8mare/fog_release
TouwaStar Aug 9, 2020
7110f79
Update requirements.txt
TouwaStar Aug 9, 2020
0d945a6
Update version.py
TouwaStar Aug 9, 2020
3903d90
Update manifest.json
TouwaStar Aug 9, 2020
a85f707
Update README.md
TouwaStar Aug 9, 2020
cc39ef9
Merge upstream
FriendsOfGalaxyBot Aug 9, 2020
a73755d
Update README.md
TouwaStar Aug 9, 2020
31c2856
up ver
urwrstkn8mare Sep 7, 2020
9f6d3ad
add cool badges!
urwrstkn8mare Sep 7, 2020
0b9fbca
update build.py to v1.0.0
urwrstkn8mare Sep 7, 2020
18e790b
simply launch() function
urwrstkn8mare Sep 8, 2020
172859f
move prepare_local_size_context() logic to get_local_size()
urwrstkn8mare Sep 8, 2020
eb4b017
update authentication ui
urwrstkn8mare Sep 8, 2020
88ae972
add INSTALL_MULTIMC.md
urwrstkn8mare Sep 9, 2020
d4ee3cd
update install-multimc link to INSTALL_MULTIMC.md
urwrstkn8mare Sep 10, 2020
dec6e5c
update update_href() function to add '&next=page2' automatically
urwrstkn8mare Sep 10, 2020
7189a90
fix: remove asyncio.run() in pass_login_credentials
urwrstkn8mare Sep 9, 2020
ac4776b
make utils folder + move existing utils to it
urwrstkn8mare Sep 9, 2020
20877fd
update utils imports
urwrstkn8mare Sep 9, 2020
bc34ae7
refactor to use .get_tracking_games()
urwrstkn8mare Sep 9, 2020
612fd42
update double_click_effect() desc.
urwrstkn8mare Sep 9, 2020
2971bb2
expose exceptions + extended TimeTracker class via time_tracker.py
urwrstkn8mare Sep 9, 2020
89a41b1
fix: use 'with open()' instead
urwrstkn8mare Sep 9, 2020
638e6ec
fix: return GameTime, not None
urwrstkn8mare Sep 9, 2020
ca035a4
fix: update download() to use seperate thread
urwrstkn8mare Sep 9, 2020
a4e4e76
fix: remove imports that broke the integration
urwrstkn8mare Sep 9, 2020
1605625
fix: await download() to get launcher_path
urwrstkn8mare Sep 9, 2020
789a9a0
fix: update imports so it works
urwrstkn8mare Sep 9, 2020
43f8c71
change size of error window
urwrstkn8mare Sep 9, 2020
a61d882
update readme
urwrstkn8mare Sep 9, 2020
a0d9104
Add TODO
urwrstkn8mare Sep 9, 2020
b8c481a
up ver
urwrstkn8mare Sep 9, 2020
1fdc9ee
add/update todo
urwrstkn8mare Sep 11, 2020
a593148
make href links in page3 close window as well
urwrstkn8mare Sep 11, 2020
a79cfbb
Moved requirements to subfolder
urwrstkn8mare Sep 11, 2020
5b531fa
add dev requirements
urwrstkn8mare Sep 11, 2020
72e8139
Using tasks.py for dev instead now
urwrstkn8mare Sep 11, 2020
073a04e
fix: should solve https://github.com/TouwaStar/Galaxy_Plugin_Minecraf…
urwrstkn8mare Sep 11, 2020
43aae90
updating build header to development for new tasks.py in README
urwrstkn8mare Sep 11, 2020
780581d
update install-multimc link to go to MultiMC's Getting Started
urwrstkn8mare Sep 12, 2020
0e393f3
fix: remove 'itch' in output path + create release dir if it doesn't …
urwrstkn8mare Sep 12, 2020
1f44270
Merge pull request #10 from urwrstkn8mare/fog_release
TouwaStar Sep 15, 2020
fc4a58c
Update version.py
TouwaStar Sep 15, 2020
e2ea20b
Update manifest.json
TouwaStar Sep 15, 2020
75e8264
Remove badges
urwrstkn8mare Sep 15, 2020
74571ce
Merge upstream
FriendsOfGalaxyBot Sep 16, 2020
fca578e
Remove `GamesStillBeingTrackedException`
urwrstkn8mare Sep 17, 2020
f9da599
Remove unnecessary `if` in `get_game_time()`
urwrstkn8mare Sep 17, 2020
aa4d709
Merge pull request #11 from urwrstkn8mare/patch-1
TouwaStar Oct 2, 2020
c73ea7b
Merge upstream
FriendsOfGalaxyBot Oct 2, 2020
3c4b4de
add colours to tasks!
urwrstkn8mare Oct 3, 2020
efca44d
raise InvalidCredentials for new users + more
urwrstkn8mare Oct 3, 2020
2b85313
Merge pull request #13 from urwrstkn8mare/fog_release
TouwaStar Nov 2, 2020
dbb4959
Update manifest.json
TouwaStar Nov 2, 2020
a10af51
Update version.py
TouwaStar Nov 2, 2020
02a85ae
Merge upstream
FriendsOfGalaxyBot Nov 2, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
*.pyc
*.pyo
*.pyo
*__pycache__
*.DS_STORE
releases
.vscode
3 changes: 3 additions & 0 deletions INSTALL_MULTIMC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
_This is a work in progress._

# See [MultiMC](https://multimc.org/)'s [getting started](https://github.com/MultiMC/MultiMC5/wiki/Getting-Started)
6 changes: 3 additions & 3 deletions current_version.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"tag_name": "0.8",
"tag_name": "0.8.3",
"assets": [
{
"browser_download_url": "https://github.com/FriendsOfGalaxy/galaxy-integration-minecraft/releases/download/0.8/macos.zip",
"browser_download_url": "https://github.com/FriendsOfGalaxy/galaxy-integration-minecraft/releases/download/0.8.3/macos.zip",
"name": "macos.zip"
},
{
"browser_download_url": "https://github.com/FriendsOfGalaxy/galaxy-integration-minecraft/releases/download/0.8/windows.zip",
"browser_download_url": "https://github.com/FriendsOfGalaxy/galaxy-integration-minecraft/releases/download/0.8.3/windows.zip",
"name": "windows.zip"
}
]
Expand Down
Binary file added example.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 0 additions & 5 deletions requirements.txt

This file was deleted.

14 changes: 14 additions & 0 deletions requirements/app.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
aiohttp==3.6.2 # via galaxy.plugin.api
async-timeout==3.0.1 # via aiohttp
attrs==19.3.0 # via aiohttp
certifi==2020.6.20 # via galaxy.plugin.api, requests
chardet==3.0.4 # via aiohttp, requests
galaxy.plugin.api==0.66.0 # via -r requirements.txt
galaxyutils==0.1.5 # via -r requirements.txt
idna==2.10 # via requests, yarl
multidict==4.7.6 # via aiohttp, yarl
requests==2.24.0 # via -r requirements.txt
send2trash==1.5.0 # via -r requirements.txt
typing-extensions==3.7.4.2 # via yarl
urllib3==1.25.10 # via requests
yarl==1.5.1 # via aiohttp
4 changes: 4 additions & 0 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-r app.txt
invoke==1.4.1
pip-tools==5.3.1
colorama==0.4.3
47 changes: 41 additions & 6 deletions src/consts.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,45 @@
import sys
if sys.platform == 'win32':
import platform, os

IS_WINDOWS = platform.system().lower() == "windows"

if IS_WINDOWS:
import winreg

REGISTRY_START_PATHS = [winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE]
MINECRAFT_REGISTRY_PATHS = ["SOFTWARE\\Mojang\\InstalledProducts\\Minecraft Launcher", "SOFTWARE\\WOW6432Node\\Mojang\\InstalledProducts\\Minecraft Launcher"]
MINECRAFT_REGISTRY_PATH_INSTALL_LOCATION_KEY = "InstallLocation"
WINDOWS_UNINSTALL_LOCATION = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
REGISTRY_START_PATHS = [winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE]
else:
REGISTRY_START_PATHS = []


class GameID:
Minecraft = "mc"
MinecraftDungeons = "mcd"
MinecraftEducationEdition = "mcedu"
FriendsOfGalaxy marked this conversation as resolved.
Show resolved Hide resolved


GAMES = [GameID.Minecraft, GameID.MinecraftDungeons]


INSTALLED_FOLDER_PATH = os.path.abspath(
os.path.expandvars("%localappdata%\\GOG.com\\Galaxy\\plugins\\installed")
if IS_WINDOWS
else os.path.expanduser("~/Library/Application Support/GOG.com/Galaxy/plugins/installed")
)

DIRNAME = os.path.abspath(os.path.join(__file__, ".."))

SOFTWARE_PATHS = ["SOFTWARE\\", "SOFTWARE\\WOW6432Node\\"]
mojang_registry_relative_location = "Mojang\\InstalledProducts\\"
GAME_REGISTY_RELATIVE_LOCATIONS = {
GameID.Minecraft: mojang_registry_relative_location + "Minecraft Launcher",
GameID.MinecraftDungeons: mojang_registry_relative_location + "Minecraft Dungeons Launcher",
}
REGISTRY_EXE_KEYS = {GameID.Minecraft: "InstallExe", GameID.MinecraftDungeons: "InstallFile"}
WIN_UNINSTALL_RELATIVE_LOCATION = "Microsoft\\Windows\\CurrentVersion\\Uninstall"
MINECRAFT_WIN_INSTALL_URL = "https://launcher.mojang.com/download/MinecraftInstaller.msi"
MINECRAFT_MAC_INSTALL_URL = "https://launcher.mojang.com/download/Minecraft.dmg"
MINECRAFT_DUNGEONS_INSTALL_URL = (
"https://launcher.mojang.com/download/MinecraftDungeonsInstaller.msi"
)


GAME_NAMES = {GameID.Minecraft: "Minecraft", GameID.MinecraftDungeons: "Minecraft Dungeons"}
167 changes: 95 additions & 72 deletions src/local.py
Original file line number Diff line number Diff line change
@@ -1,84 +1,107 @@
import os, logging

import sys
if sys.platform == 'win32':
from consts import (
GameID,
REGISTRY_START_PATHS,
SOFTWARE_PATHS,
GAME_REGISTY_RELATIVE_LOCATIONS,
REGISTRY_EXE_KEYS,
WIN_UNINSTALL_RELATIVE_LOCATION,
IS_WINDOWS,
)
from utils import misc


if IS_WINDOWS:
import winreg

from consts import MINECRAFT_REGISTRY_PATHS, REGISTRY_START_PATHS, MINECRAFT_REGISTRY_PATH_INSTALL_LOCATION_KEY, WINDOWS_UNINSTALL_LOCATION
log = logging.getLogger(__name__)

import logging as log
import os
import psutil
import asyncio

class LocalClient():
class LocalClient:
def __init__(self):
self.running_process = None

async def get_size_at_path(self, start_path):
total_size = 0
for dirpath, dirnames, filenames in os.walk(start_path):
for f in filenames:
await asyncio.sleep(0)
fp = os.path.join(dirpath, f)
if not os.path.islink(fp):
total_size += os.path.getsize(fp)

return total_size

def get_minecraft_launcher_path(self):
if sys.platform == 'win32':
install_path = self.get_minecraft_folder_path()
potential_path = os.path.join(install_path, 'MinecraftLauncher.exe')
if os.path.exists(potential_path):
return potential_path
else:
return self.get_minecraft_folder_path()

def get_minecraft_folder_path(self):
if sys.platform == 'win32':
for start_path in REGISTRY_START_PATHS:
for minecraft_reg_path in MINECRAFT_REGISTRY_PATHS:
try:
reg = winreg.ConnectRegistry(None, start_path)
with winreg.OpenKey(reg, minecraft_reg_path) as key:
install_path = winreg.QueryValueEx(key, MINECRAFT_REGISTRY_PATH_INSTALL_LOCATION_KEY)[0]
except OSError:
continue
if os.path.exists(install_path):
return install_path
else:
potential_path = "/Applications/Minecraft.app"
if os.path.exists(potential_path):
return potential_path
self.running_games = {
GameID.Minecraft: None,
GameID.MinecraftDungeons: None,
}

def find_launcher_path(self, game_id, *, folder=False, folder_path=None, exe=None) -> str:
if exe is None and folder_path is not None:
folder_path = None
if exe is not None and folder_path is None:
folder_path = exe
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't be os.path.dirname(exe)?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah sorry, the code for that is a little messy over the multiple classes. Basically, that line is for Mac when the subclass returns the path to Minecraft.app. The thing is that's both the executable and the folder! That's why it's necessary but I could probably clean it up a little.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ou, I see. In this case the best would be to inject OS implementation to LocalClient (composition) and expose only higher level methods in LocalClient (like run or whatever you need there). Or, to avoid refactor just put some "if" statements. It is better to have more code but explicite.

if WINDOWS:
    do_this()
else:
    do_that()

Copy link
Owner

@FriendsOfGalaxy FriendsOfGalaxy Sep 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

every folder is executable BTW. "Running" .app folders on Mac is just a syntastic sugar for system layer to run proper executable in x.app/Contents/MacOS

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case the best would be to inject OS implementation to LocalClient (composition) and expose only higher level methods in LocalClient (like run or whatever you need there).

Yes, I definitely need to refactor local client to be better, in fact I kind of started halfway with the launch functions but then stopped because it was working. I'll work on it anyway :)

"Running" .app folders on Mac is just a syntastic sugar for system layer to run proper executable in x.app/Contents/MacOS.

Absolutely did not know that, thanks a lot for that info.

if exe is not None and folder_path is not None:
folder_path = os.path.abspath(folder_path)
exe = os.path.abspath(exe)
log.debug(f"folder path for {game_id}: {folder_path}")
log.debug(f"path for {game_id}: {exe}")
return exe if not folder else folder_path
Comment on lines +28 to +38
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is hard to follow this logic. You may consider refactor in the future to make it more maintainable. I would limit purposes and simplify the method interface, or at least document it /cover with tests.

But for now, better do not change anything if it works :) (I see that it is used in many places around the code)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I've touched on the badness of this code in this reply to one of your other comments (here). Basically you are completely correct. It does work so I'm not touching it but definitely it would be better if a refactor it in the future.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a tip for the future: follow single responsibility rule. Keep logic in relevant layer. Do simple interfaces: single method that do single simple thing like: find_launcher_dir() (without arguments that modify the inner logic). Such method should return always path to launcher and that's it. Then you can create find_executable(directory, [game_id](if really needed)) to get exact executable and run() method separate for Mac and Windows that utilize other methods under the hood.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks that's very true, I will be doing some heavy refactoring in local.py

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not refactor until we merge current working state :)


def is_game_still_running(self, game_id) -> bool:
return self.running_games[game_id] and self.running_games[game_id].poll() is None

def find_minecraft_uninstall_command(self):
if sys.platform == 'win32':
reg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
with winreg.OpenKey(reg, WINDOWS_UNINSTALL_LOCATION) as key:
def launch(self, game_id):
log.info(f"Launching {game_id}")
self.running_games[game_id] = misc.open_path(self.find_launcher_path(game_id))

def uninstall(game_id):
pass


class WindowsLocalClient(LocalClient):
def find_launcher_path(self, game_id, folder=False):
for start_path in REGISTRY_START_PATHS:
for software_path in SOFTWARE_PATHS:
reg = winreg.ConnectRegistry(None, start_path)
try:
with winreg.OpenKey(
reg, software_path + GAME_REGISTY_RELATIVE_LOCATIONS[game_id]
) as key:
directory = winreg.QueryValueEx(key, "InstallLocation")[0]
return super().find_launcher_path(
game_id,
folder=folder,
folder_path=directory,
exe=os.path.join(
directory, winreg.QueryValueEx(key, REGISTRY_EXE_KEYS[game_id])[0]
),
)
except OSError:
pass
return super().find_launcher_path(game_id, folder=folder)

def uninstall(self, game_id):
targetDisplayName = None
if game_id == GameID.Minecraft:
targetDisplayName = "Minecraft Launcher"
elif game_id == GameID.MinecraftDungeons:
targetDisplayName = "Minecraft Dungeons Launcher"
for start_path in REGISTRY_START_PATHS:
for software_path in SOFTWARE_PATHS:
reg = winreg.ConnectRegistry(None, start_path)
try:
key = winreg.OpenKey(reg, software_path + WIN_UNINSTALL_RELATIVE_LOCATION)
except OSError:
continue
for i in range(0, winreg.QueryInfoKey(key)[0]):
try:
subkey_name = winreg.EnumKey(key, i)
with winreg.OpenKey(key, subkey_name) as subkey:
if winreg.QueryValueEx(subkey,'DisplayName')[0] == 'Minecraft Launcher':
return winreg.QueryValueEx(subkey, 'UninstallString')[0]
if winreg.QueryValueEx(subkey, "DisplayName")[0] == targetDisplayName:
misc.run(winreg.QueryValueEx(subkey, "UninstallString")[0])
return
except OSError:
continue
else:
pass

def is_minecraft_still_running(self):
if self.running_process and self.running_process.is_running():
return True
elif self.running_process and not self.running_process.is_running():
self.running_process = None
return False

async def was_minecraft_launched(self, process_iter_interval=0.15):
for process in psutil.process_iter(attrs=['name', 'exe'], ad_value=''):
await asyncio.sleep(process_iter_interval)
if process.info['name'].lower() == "minecraftlauncher.exe" or process.info['exe'] == "/Applications/Minecraft.app/Contents/MacOS/launcher":
log.info(f"Found a running game!")
self.running_process = process
return True
self.running_process = None
return False
pass
winreg.CloseKey(key)


class MacLocalClient(LocalClient):
def find_launcher_path(self, game_id, *, folder=False):
if game_id == GameID.Minecraft:
potential_path = "/Applications/Minecraft.app"
if os.path.exists(potential_path):
return super().find_launcher_path(game_id, folder=folder, exe=potential_path)
return super().find_launcher_path(game_id, folder=folder)

def uninstall(self, game_id):
misc.send2trash(self.find_launcher_path(game_id, folder=True))
22 changes: 11 additions & 11 deletions src/manifest.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "Galaxy Minecraft plugin",
"platform": "minecraft",
"guid": "cb57391f-1675-35b1-05c0-896d43bdf8f4",
"version": "0.8.3",
"description": "Galaxy Minecraft plugin",
"author": "TouwaStar",
"email": "yowosek@gmail.com.com",
"url": "https://github.com/TouwaStar/Galaxy_Plugin_Minecraft",
"script": "plugin.py",
"update_url": "https://raw.githubusercontent.com/FriendsOfGalaxy/galaxy-integration-minecraft/master/current_version.json"
}
"name": "Galaxy Minecraft plugin",
"platform": "minecraft",
"guid": "cb57391f-1675-35b1-05c0-896d43bdf8f4",
"version": "1.0.3",
"description": "Galaxy Minecraft plugin",
"author": "TouwaStar",
"email": "yowosek@gmail.com.com",
"url": "https://github.com/TouwaStar/Galaxy_Plugin_Minecraft",
"script": "plugin.py",
"update_url": "https://raw.githubusercontent.com/FriendsOfGalaxy/galaxy-integration-minecraft/master/current_version.json"
}
57 changes: 57 additions & 0 deletions src/multimc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import os, logging

from galaxy.api.plugin import GameTime

from consts import IS_WINDOWS, GameID
from utils import misc

log = logging.getLogger(__name__)


class PathNotExectuable(Exception):
pass


class MultiMCClient:
def __init__(self, path: str):
self.path = os.path.expanduser(os.path.expandvars(os.path.abspath(path)))
if not os.access(path, os.X_OK):
raise PathNotExectuable
self.folder = os.path.dirname(self.path) if IS_WINDOWS else self.path
log.debug(f"MultiMC Path: {self.path}")
self.instances_path = (
os.path.join(self.folder, "instances")
if IS_WINDOWS
else os.path.join(self.folder, "Contents", "MacOS", "instances")
)
log.debug(f"MultiMC instances path: {self.instances_path}")
self.process = None

def get_time(self):
time = 0 # in seconds
lastPlayed = None
for f in os.scandir(self.instances_path):
if f.is_dir():
cfg_path = os.path.join(f.path, "instance.cfg")
if os.path.isfile(cfg_path):
with open(cfg_path, "r") as f:
for line in f.readlines():
split_line = line.strip().split("=")
if split_line[0] == "totalTimePlayed":
time += int(split_line[1])
elif split_line[0] == "lastLaunchTime":
lastPlayed = misc.compare(lastPlayed, int(split_line[1]))
log.debug(f"Got total MultiMC Time: {time / 60}")
return GameTime(GameID, time / 60, lastPlayed)

def launch(self):
self.process = misc.open_path(self.path)

def running(self):
if self.process is None:
return False
elif self.process.poll() is None:
return True
else:
self.process = None
return False
Loading