Skip to content

Commit 0f205c7

Browse files
committed
Reimplement the download function
Now one or more versions can be listed to be downloaded, and also the downloaded jars will be saved and reused (that probably wasn't possible before because it was always just a single minecraft.jar back then and keeping track of distinct versions would be hard). Additionally the username and password options have been removed, since they don't serve a purpose nowadays (I think they might have back then, though?). Finally, a -D (capital) option has been added to download the latest snapshot, similar to what the original download option would have been like. Also fixes #10.
1 parent 2d31d33 commit 0f205c7

File tree

4 files changed

+93
-71
lines changed

4 files changed

+93
-71
lines changed

README.md

+11-4
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,24 @@ a few specifically. Each topping is then aggregated by
1111

1212
## Usage
1313
The simplest way to use Burger is to pass the `-d` or `--download`
14-
flag, which will download the minecraft client for you.
14+
flag, which will download the specified minecraft client for you.
15+
This option can be specified multiple times. The downloaded jar will be saved
16+
in the working directory, and if it already exists the existing verison will be used.
1517

16-
$ python munch.py --download
18+
$ python munch.py --download 1.13.2
19+
20+
To download the latest snapshot, `-D` or `--download-latest` can be used.
21+
22+
$ python munch.py -D
1723

1824
Alternatively, you can specify the client JAR by passing it as an argument.
1925

2026
$ python munch.py 1.8.jar
2127

2228
You can redirect the output from the default `stdout` by passing
23-
`-o <path>` or `--output <path>`.
24-
29+
`-o <path>` or `--output <path>`. This is useful when combined with
30+
verbose output (`-v` or `--verbose`) so that the output doesn't go into the file.
31+
2532
$ python munch.py -d --output output.json
2633

2734
You can see what toppings are available by passing `-l` or `--list`.

burger/toppings/sounds.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
import six
3333
import six.moves.urllib.request
3434

35-
from burger.website import Website
35+
from burger import website
3636
from .topping import Topping
3737

3838
from jawa.constants import *
@@ -71,14 +71,14 @@ class SoundTopping(Topping):
7171
def act(aggregate, classloader, verbose=False):
7272
sounds = aggregate.setdefault('sounds', {})
7373
try:
74-
version_meta = Website.get_version_meta(aggregate["version"]["name"], verbose)
74+
version_meta = website.get_version_meta(aggregate["version"]["name"], verbose)
7575
except Exception as e:
7676
if verbose:
7777
print("Error: Failed to download version meta for sounds: %s" % e)
7878
traceback.print_exc()
7979
return
8080
try:
81-
assets = Website.get_asset_index(version_meta, verbose)
81+
assets = website.get_asset_index(version_meta, verbose)
8282
except Exception as e:
8383
if verbose:
8484
print("Error: Failed to download asset index for sounds: %s" % e)

burger/website.py

+58-40
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2222
THE SOFTWARE.
2323
"""
24+
import os
2425
import six.moves.urllib.request
2526

2627
try:
@@ -31,53 +32,70 @@
3132
VERSION_MANIFEST = "https://launchermeta.mojang.com/mc/game/version_manifest.json"
3233
LEGACY_VERSION_META = "https://s3.amazonaws.com/Minecraft.Download/versions/%(version)s/%(version)s.json" # DEPRECATED
3334

35+
_cached_version_manifest = None
36+
_cached_version_metas = {}
37+
3438
def _load_json(url):
3539
stream = six.moves.urllib.request.urlopen(url)
3640
try:
3741
return json.load(stream)
3842
finally:
3943
stream.close()
4044

41-
class Website(object):
42-
def __init__(self, username, password, version=999999):
43-
self.username = username
44-
self.password = password
45-
self.version = version
46-
47-
@staticmethod
48-
def get_version_meta(version, verbose):
49-
"""
50-
Gets a version JSON file, first attempting the to use the version manifest
51-
and then falling back to the legacy site if that fails.
52-
Note that the main manifest should include all versions as of august 2018.
53-
"""
54-
version_manifest = _load_json(VERSION_MANIFEST)
55-
for version_info in version_manifest["versions"]:
56-
if version_info["id"] == version:
57-
address = version_info["url"]
58-
break
59-
else:
60-
if verbose:
61-
print("Failed to find %s in the main version manifest; using legacy site" % version)
62-
address = LEGACY_VERSION_META % {'version': version}
63-
if verbose:
64-
print("Loading version manifest for %s from %s" % (version, address))
65-
return _load_json(address)
66-
67-
@staticmethod
68-
def get_asset_index(version_meta, verbose):
69-
"""Downloads the Minecraft asset index"""
70-
if "assetIndex" not in version_meta:
71-
raise Exception("No asset index defined in the version meta")
72-
asset_index = version_meta["assetIndex"]
45+
def get_version_manifest():
46+
global _cached_version_manifest
47+
if _cached_version_manifest:
48+
return _cached_version_manifest
49+
50+
_cached_version_manifest = _load_json(VERSION_MANIFEST)
51+
return _cached_version_manifest
52+
53+
def get_version_meta(version, verbose):
54+
"""
55+
Gets a version JSON file, first attempting the to use the version manifest
56+
and then falling back to the legacy site if that fails.
57+
Note that the main manifest should include all versions as of august 2018.
58+
"""
59+
if version in _cached_version_metas:
60+
return _cached_version_metas[version]
61+
62+
version_manifest = get_version_manifest()
63+
for version_info in version_manifest["versions"]:
64+
if version_info["id"] == version:
65+
address = version_info["url"]
66+
break
67+
else:
7368
if verbose:
74-
print("Assets: id %(id)s, url %(url)s" % asset_index)
75-
return _load_json(asset_index["url"])
69+
print("Failed to find %s in the main version manifest; using legacy site" % version)
70+
address = LEGACY_VERSION_META % {'version': version}
71+
if verbose:
72+
print("Loading version manifest for %s from %s" % (version, address))
73+
meta = _load_json(address)
7674

75+
_cached_version_metas[version] = meta
76+
return meta
77+
78+
def get_asset_index(version_meta, verbose):
79+
"""Downloads the Minecraft asset index"""
80+
if "assetIndex" not in version_meta:
81+
raise Exception("No asset index defined in the version meta")
82+
asset_index = version_meta["assetIndex"]
83+
if verbose:
84+
print("Assets: id %(id)s, url %(url)s" % asset_index)
85+
return _load_json(asset_index["url"])
86+
87+
88+
def client_jar(version, verbose):
89+
"""Downloads a specific version, by name"""
90+
filename = version + ".jar"
91+
if not os.path.exists(filename):
92+
meta = get_version_meta(version, verbose)
93+
url = meta["downloads"]["client"]["url"]
94+
if verbose:
95+
print("Downloading %s from %s" % (version, url))
96+
six.moves.urllib.request.urlretrieve(url, filename=filename)
97+
return filename
7798

78-
@staticmethod
79-
def client_jar(path=None, reporthook=None, version="1.9"):
80-
url = "http://s3.amazonaws.com/Minecraft.Download/versions/%s/%s.jar" % (version, version)
81-
#url = "http://s3.amazonaws.com/MinecraftDownload/minecraft.jar" # 1.5.2
82-
r = six.moves.urllib.request.urlretrieve(url, filename=path, reporthook=reporthook)
83-
return r[0]
99+
def latest_client_jar(verbose):
100+
manifest = get_version_manifest()
101+
return client_jar(manifest["latest"]["snapshot"], verbose)

munch.py

+21-24
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
from jawa.classloader import ClassLoader
3838
from jawa.transforms import simple_swap, expand_constants
3939

40-
from burger.website import Website
40+
from burger import website
4141
from burger.roundedfloats import transform_floats
4242

4343

@@ -84,18 +84,16 @@ def import_toppings():
8484
try:
8585
opts, args = getopt.gnu_getopt(
8686
sys.argv[1:],
87-
"t:o:vu:p:dlcs:",
87+
"t:o:vd:Dlc",
8888
[
8989
"toppings=",
9090
"output=",
9191
"verbose",
92-
"username=",
93-
"password=",
94-
"download",
92+
"download=",
93+
"download-latest",
9594
"list",
9695
"compact",
97-
"url=",
98-
"source="
96+
"url="
9997
]
10098
)
10199
except getopt.GetoptError as err:
@@ -106,9 +104,8 @@ def import_toppings():
106104
toppings = None
107105
output = sys.stdout
108106
verbose = False
109-
username = None
110-
password = None
111-
download_fresh_jar = False
107+
download_jars = []
108+
download_latest = False
112109
list_toppings = False
113110
compact = False
114111
url = None
@@ -117,20 +114,18 @@ def import_toppings():
117114
if o in ("-t", "--toppings"):
118115
toppings = a.split(",")
119116
elif o in ("-o", "--output"):
120-
output = open(a, "a")
117+
output = open(a, "w")
121118
elif o in ("-v", "--verbose"):
122119
verbose = True
123120
elif o in ("-c", "--compact"):
124121
compact = True
125-
elif o in ("-u", "--username"):
126-
username = a
127-
elif o in ("-p", "--password"):
128-
password = a
129122
elif o in ("-d", "--download"):
130-
download_fresh_jar = True
123+
download_jars.append(a)
124+
elif o in ("-D", "--download-latest"):
125+
download_latest = True
131126
elif o in ("-l", "--list"):
132127
list_toppings = True
133-
elif o in ("-s", "--url", "--source"):
128+
elif o in ("-s", "--url"):
134129
url = a
135130

136131
# Load all toppings
@@ -213,10 +208,14 @@ def __repr__(self):
213208

214209
jarlist = args
215210

216-
# Should we download a new copy of the JAR directly
217-
# from minecraft.net?
218-
if download_fresh_jar:
219-
client_path = Website.client_jar()
211+
# Download any jars that have already been specified
212+
for version in download_jars:
213+
client_path = website.client_jar(version, verbose)
214+
jarlist.append(client_path)
215+
216+
# Download a copy of the latest snapshot jar
217+
if download_latest:
218+
client_path = website.latest_client_jar(verbose)
220219
jarlist.append(client_path)
221220

222221
# Download a JAR from the given URL
@@ -265,9 +264,7 @@ def __repr__(self):
265264
else:
266265
json.dump(transform_floats(summary), output)
267266

268-
# Cleanup temporary downloads
269-
if download_fresh_jar:
270-
os.remove(client_path)
267+
# Cleanup temporary downloads (the URL download is temporary)
271268
if url:
272269
os.remove(url_path)
273270
# Cleanup file output (if used)

0 commit comments

Comments
 (0)