SMCL – 使用Python编写简单Minecraft启动器

注意:本文最后更新于 6年 前。

Simple Minecraft Launcher,一个使用python3编写的轻量级Minecraft启动器。

代码见:http://ideone.com/aVWnVh , Github地址:https://github.com/WuSiYu/smcl。直接不加任何参数运行脚本会显示帮助和用法,这里就不再多说了。

 

下面介绍原理:

其实Minecraft这个东西,是可以用一句命令直接启动的。但由于java的尿性,-cp=”xxxx.jar:xxxxx.jar”这个加载用到的库的参数会非常的长,再加上Minecraft本身又有一堆参数,所以这个“一句命令”虽说是一句,却有一千多个字符长。。。

所以就有了启动器这么个玩意,说白了它的功能就是生成启动命令,然后执行它。

听起来虽然蛋疼,不过好在Minecraft的每个版本都会有一个json文件,里面详细的写明了用到的库、asset名、参数、主类等信息,只有解析它即可,并不复杂。

而关于盗版的问题,只要将参数中的user_type设置为Legacy即可直接跳过验证来启动,这大概是游戏界最简单的“破解”了吧。其实这是Mojang并不特别反对盗版的原因,要不然也不会这么轻松。

反正要是有钱还是都去买个正版吧,这么良心的游戏不多了。(某穷b说道。。。)

 

—– 2016-04-30 更新 —–

详细用法:

首先,这是一个命令行程序,没有界面的。而且需要命令行参数来用。

如果没有任何参数输入,则会显示帮助信息并退出。

下面是命令行参数的详细说明,python命令和脚本名视情况而定:

基本用法:
python3 SMCL.py [-d minecraft所在目录] [-v 要启动的版本] [-m JAVA最大内存] 你的游戏ID

前三项可选,实际使用时去掉括号。游戏ID是必须的,如果没有写则不能启动。

如果minecraft所在目录未指定,则使用当前目录下的.minecraft目录

如果要启动的版本未指定,则会启动minecraft目录中最新的那个版本

如果最大内存未指定,则会设置为2048m,也就是2G

下面是一些栗子:

游戏ID:WuSiYu, minecraft目录为当前目录下的.minecraft目录(默认值),启动minecraft目录中最新的那个版本(默认值), JAVA最大内存为2G(默认值):

python3 SMCL.py WuSiYu

 

游戏ID:WuSiYu, minecraft目录为当前目录(将脚本放到.minecraft目录里时用这个),启动minecraft目录中最新的那个版本(默认值), JAVA最大内存为2G(默认值):

python3 SMCL.py -d . WuSiYu

 

游戏ID:WuSiYu, minecraft目录为当前目录(将脚本放到.minecraft目录里时用这个), 启动1.7.10版本,JAVA最大内存为2G(默认值):

python3 SMCL.py -d . -v 1.7.10 WuSiYu

 

游戏ID:WuSiYu, minecraft目录为当前目录(将脚本放到.minecraft目录里时用这个), 启动1.7.10版本,JAVA最大内存为8G(也就是8192m):

python3 SMCL.py -d . -v 1.7.10 -m 8192m WuSiYu

 

PS:我现在还在继续编写这个启动器,预计会加入下载等功能

—– 16-04-30 更新结束 —–

 

下面附上完整代码:

#!/usr/bin/python3
import os, json, sys

# default value
MinecraftDir = './.minecraft'
Version = ''
maxMen = '2048m'
ID = ''

# get jar files path from the json file
def getJars(minecraftDir, version):
    jsonFilePath = minecraftDir+'/versions/'+version+'/'+version+'.json'

    with open(jsonFilePath, 'r') as jsonFile :
        jsonFileContent = jsonFile.read()

    jsonFileKeys = json.loads( jsonFileContent )

    jars = ''
    for x in jsonFileKeys['libraries']:
        jarFileParts = x['name'].split(':')
        jarFile =    MinecraftDir+'/libraries/' + \
                    jarFileParts[0].replace('.','/')+'/'+jarFileParts[1] +'/'+jarFileParts[2] + '/' + \
                    jarFileParts[1]+'-'+jarFileParts[2]+'.jar'

        jars += jarFile+':'
    
    if 'inheritsFrom' in jsonFileKeys.keys():
        jars += getJars(minecraftDir, jsonFileKeys['inheritsFrom'])

    return jars

# generate the Minecraft Argvs from the json file
def getMinecraftArgvs(minecraftDir, version, ID):
    jsonFilePath = minecraftDir+'/versions/'+version+'/'+version+'.json'
    with open(jsonFilePath, 'r') as jsonFile :
        jsonFileContent = jsonFile.read()

    jsonFileKeys = json.loads( jsonFileContent )
    argvs = jsonFileKeys['minecraftArguments']
    argvs = argvs    .replace('${auth_player_name}', ID)\
                    .replace('${version_name}', '{}')\
                    .replace('${game_directory}', minecraftDir)\
                    .replace('${assets_root}', minecraftDir+'/assets')\
                    .replace('${assets_index_name}', jsonFileKeys['assets'])\
                    .replace('${auth_uuid}', '{}')\
                    .replace('${auth_access_token}', '{}')\
                    .replace('${user_type}', 'Legacy')\
                    .replace('${version_type}', jsonFileKeys['type'])\
                    .replace('${user_properties}', '{}')
    argvs = jsonFileKeys['mainClass'] + ' ' + argvs
    return argvs


# process argvs for this script
job = 0
theUsageText = 'Usage:\t\t'+sys.argv[0]+' [-d Minecraft_dir] [-v version] [-m 2048m] Username\n\t\t\tLaunch Minecraft\n\n\t\t'+sys.argv[0]+' [-d Minecraft_dir] -l\n\t\t\tList Minecraft versions'

if len(sys.argv) == 1:
    print(theUsageText)
    sys.exit()
else:
    t=1
    while t<len(sys.argv):
        if sys.argv[t] == '-d':
            t+=1
            MinecraftDir = sys.argv[t]
        elif sys.argv[t] == '-v':
            t+=1
            Version = sys.argv[t]
        elif sys.argv[t] == '-m':
            t+=1
            maxMen = sys.argv[t]
        elif sys.argv[t] == '-h':
            print(theUsageText)
            sys.exit()
        elif sys.argv[t] == '-l':
            job = 1
        else:
            ID = sys.argv[t]

        t+=1

if job == 1:        #if the job is list Minecraft versions, do it and exit
    print('Minecraft versions:')
    versions = os.listdir(MinecraftDir+'/versions/')
    versions.sort(reverse=True)
    for x in versions:
        print( '\t'+x )
    sys.exit()

if ID == '':        #if do not specify a ID, print the usage and exit
    print(theUsageText)
    sys.exit()

if Version == '':    #if do not specify a version, set the Version value to the latest version
    versions = os.listdir(MinecraftDir+'/versions/')
    versions.sort(reverse=True)
    Version = versions[0]
# end of this part


# generate command to launch Minecraft
befour = 'java -Xincgc -XX:-UseAdaptiveSizePolicy -XX:-OmitStackTraceInFastThrow -Xmn128m -Xmx'+maxMen+' -Djava.library.path='+MinecraftDir+'/versions/'+Version+'/'+Version+'-natives -Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true -Duser.home=/ -cp "'

after = getMinecraftArgvs(MinecraftDir, Version ,ID)

jars = getJars(MinecraftDir, Version)
jars += MinecraftDir+'/versions/'+Version+'/'+Version+'.jar" '

cmd = befour + jars + after
# end of this part


# launch Minecraft
os.system(cmd)

作者:WuSiYu

学生,Web开发者,智能硬件&IOT爱好者

15条评论

    1. 把代码存为.py文件,然后在终端里用python运行它就可以了。
      命令行参数会提示的。

      其实这个启动器的功能十分简单,仅仅是能启动Minecraft。写这个的目的其实主要是为了给做服里的专用客户端做准备。
      要是日常使用,我还是推荐使用HMCL这种比较成熟的启动器。

      1. 谢谢回复,but出现了些问题
        1. 该代码已存档成 .py文件
        2. .minecraft的文件也放在同一个文件夹里面
        3. 也已添加用户名和Version

        运行时,cmd 出现
        [-d Minecraft_dir] [-v version] [-m 2048m] Username
        Launch Minecraft
        [-d Minecraft_dir]
        List Minecraft versions

        请问程式中的那一部分还需要进行修改的呢><

        1. 输出这个是正常的。
          这是一个命令行程序,需要通过命令行参数来运行。
          如果没有参数输入,则会输出帮助信息。

          正确的使用方法是:python3 xxxx.py -v 要启动的版本 -d minecraft的目录 -m 最大的内存 你的ID

          前3个参数是可选的,而ID是必须的。

          更详细的说明等我更新一下文章

          PS:抱歉这么晚才看到

      2. Volkswagen is a good brand and Jetta is a good model. Go for it if you do2&8#n17;t mind its look because many people don’t like it. Many friends of mine who own Jetta from 1998 model to latest model, no one has any complaint so far.

  1. 请教一下,java的参数我不是很懂,-Xincgc是什么意思呢?我运行的时候说“Unrecognized option: -Xincgc”

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注