Last active
November 18, 2023 12:20
-
-
Save geoffp/3e2b5e22acf0a4becd8edc18e1caf546 to your computer and use it in GitHub Desktop.
A simple launcher to allow you to launch minecraft with a specified displayName so a family can play on the same server with one account. Works on Linux, probably Mac OS too. Change the constants to suit your needs.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import json, sys, os, subprocess, time, signal, sys | |
# | |
# Constants | |
# | |
# First and only argument is the player's display name | |
playerName = sys.argv[1] if len(sys.argv) > 1 else None | |
if sys.platform == 'darwin': | |
jsonPath = os.path.expanduser(os.path.join('~', 'Library', 'Application Support', 'Minecraft', 'launcher_profiles.json')) | |
minecraftPath = "/Applications/Minecraft.app" | |
else: | |
jsonPath = os.path.expanduser(os.path.join('~', '.minecraft', 'launcher_profiles.json')) | |
minecraftPath = os.path.expanduser(os.path.join('~', 'bin', 'Minecraft.jar')) | |
# | |
# Free Functions | |
# | |
def lockFile(): | |
os.chmod(jsonPath, 0o444) | |
def unlockFile(): | |
os.chmod(jsonPath, 0o644) | |
def getDisplayNameParent(jsonData): | |
auths = jsonData['authenticationDatabase'] | |
# We assume that there's only only entry in the authenticationDatabase | |
# dictionary, so this should loop only once and work fine. | |
for authId in auths: | |
if 'profiles' in auths[authId]: | |
# same here. it's a loop, but just a lazy way to get the first and | |
# only dict entry | |
for profileId in auths[authId]['profiles']: | |
return auths[authId]['profiles'][profileId] | |
else: | |
return auths[authId] | |
# If we get here, we found nothing! | |
return None | |
def getUserName(): | |
with open(jsonPath) as jsonFile: | |
data = json.load(jsonFile) | |
displayNameParent = getDisplayNameParent(data) | |
if displayNameParent != None: | |
return displayNameParent['displayName'] | |
return None | |
def changeUserName(): | |
with open(jsonPath) as jsonFile: | |
data = json.load(jsonFile) | |
displayNameParent = getDisplayNameParent(data) | |
if displayNameParent != None: | |
displayNameParent['displayName'] = playerName | |
with open(jsonPath, 'w') as jsonFile: | |
json.dump(data, jsonFile, indent=2) | |
def killLauncher(launcher): | |
if sys.platform == 'darwin': | |
subprocess.call(['killall', 'launcher']) | |
else: | |
launcher.kill() | |
def startLauncher(): | |
if sys.platform == 'darwin': | |
execPath = ['open', '-W', minecraftPath] | |
else: | |
execPath = ['java', '-jar', minecraftPath] | |
# launch it! | |
launcher = subprocess.Popen(execPath) | |
# the callback for handling a ctrl-c | |
def signal_handler(signal, frame): | |
print('You pressed Ctrl+C! Killing the launcher...') | |
killLauncher(launcher); | |
sys.exit(0) | |
# register callback for handling ctrl-c | |
signal.signal(signal.SIGINT, signal_handler) | |
# return the launcher | |
return launcher | |
# | |
# Main procedure: if a player name was given, alter the file | |
# accordingly. Otherwise, just unlock the file so a login is | |
# possible. Either way, launch Minecraft. | |
# | |
if (playerName): | |
unlockFile() | |
changeUserName() | |
# lockFile() | |
else: | |
unlockFile() | |
# OK, let's try it... | |
# New idea: loop and sleep, checking the username every 2 seconds or so | |
launcher = startLauncher() | |
print "Watching for an auth refresh..." | |
while launcher.poll() == None: | |
# wait for a bit... | |
time.sleep(1) | |
currentUserName = getUserName() | |
# if the user name is None, there's no authentication at | |
# all. Gotte get one before we can proceed. | |
if currentUserName == None: | |
print "Waiting for login..." | |
continue | |
# if the user name has switched back after an auth token refresh, let's try this again... | |
if currentUserName != playerName: | |
print "Hey, it looks like the display name was reset by an auth refresh, hang on, I need to restart the launcher... " | |
killLauncher(launcher) | |
changeUserName() | |
launcher = startLauncher() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment