-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathgen_pack.py
More file actions
207 lines (176 loc) · 7.77 KB
/
gen_pack.py
File metadata and controls
207 lines (176 loc) · 7.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""This script can automatically generate blockstate and block model files for the Round Trees resourcepack."""
import argparse
import json
import os
import zipfile
import shutil
import time
from distutils.dir_util import copy_tree
import src.json_utils
from src.json_utils import dumpJson, minifyJsonFiles, minify
# Utility functions
def printGreen(out): print("\033[92m{}\033[00m".format(out))
def printCyan(out): print("\033[96m{}\033[00m" .format(out))
def printOverride(out): print(" -> {}".format(out))
def autoGen(jsonData, args):
print("Generating assets...")
if (os.path.exists("./assets")): shutil.rmtree("./assets")
copy_tree("./base/assets/", "./assets/")
if minify: minifyJsonFiles()
filecount = 0
unpackMods()
scanModsForLogs()
for root, dirs, files in os.walk("./input/assets"):
for infile in files:
if (len(root.split("/")) > 3) and root.endswith("models/block"):
namespace = root.split("/")[3]
block_id = infile.replace(".json", "")
print(namespace+":"+block_id)
textures = readTextures(root, infile, namespace, block_id)
generateBlockstateAndModel(namespace, block_id, textures["end"], textures["side"])
filecount += 1
# End of autoGen
print()
cleanupMods()
printCyan("Processed {} log blocks".format(filecount))
def readTextures(root, infile, namespace, block_id) -> dict[str, str]:
with open(os.path.join(root, infile), "r") as rf:
textures = json.load(rf)["textures"]
texture_end = None
texture_side = None
for key in ["end", "up"]:
if key in textures:
texture_end = textures[key]
break
for key in ["side", "north"]:
if key in textures:
texture_side = textures[key]
break
if texture_end == None:
printOverride("Could not determine top texture in base model, using fallback")
texture_end = f"{namespace}:{block_id}_top"
if texture_side == None:
printOverride("Could not determine side texture in base model, using fallback")
texture_side = f"{namespace}:{block_id}"
return {"end": texture_end, "side": texture_side}
def unpackMods():
for root, dirs, files in os.walk("./input/mods"):
for infile in files:
if infile.endswith(".jar"):
print("Unpacking mod: "+infile)
zf = zipfile.ZipFile(os.path.join(root, infile), 'r')
zf.extractall(os.path.join(root, infile.replace(".jar", "_temp")))
zf.close()
def cleanupMods():
if (os.path.exists("./input/mods")): shutil.rmtree("./input/mods")
os.makedirs("./input/mods")
def scanModsForLogs():
for root, dirs, files in os.walk("./input/mods"):
for infile in files:
if len(root.split("assets")) > 1:
assetpath = root.split("assets")[1][1:]
modid = assetpath.split("models/block")[0].replace("/", "")
if "models/block" in root and infile.endswith("_log.json"):
print(f"Found log model {assetpath}/{infile} in mod {modid}")
inputfolder = os.path.join("./input/assets/", assetpath)
os.makedirs(inputfolder, exist_ok=True)
shutil.copyfile(os.path.join(root, infile), os.path.join(inputfolder, infile))
def generateBlockstateAndModel(mod_namespace, block_name, texture_end, texture_side, texture_inner = None):
# Create structure for blockstate file
block_state_file = f"assets/{mod_namespace}/blockstates/{block_name}.json"
block_state_data = {
"variants": {
"axis=y": { "model": f"{mod_namespace}:block/{block_name}" },
"axis=z": { "model": f"{mod_namespace}:block/{block_name}", "x": 90, "y": 180 },
"axis=x": { "model": f"{mod_namespace}:block/{block_name}", "x": 90, "y": 90 }
}
}
# Create blockstates folder if it doesn't exist already
if not os.path.exists("assets/{}/blockstates/".format(mod_namespace)):
os.makedirs("assets/{}/blockstates/".format(mod_namespace))
# Write blockstate file
with open(block_state_file, "w") as f:
dumpJson(block_state_data, f)
# Create models folder if it doesn't exist already
if not os.path.exists("assets/{}/models/block/".format(mod_namespace)):
os.makedirs("assets/{}/models/block/".format(mod_namespace))
# Create structure for block model file
block_model_file = f"assets/{mod_namespace}/models/block/{block_name}.json"
if "hollow_" in block_name:
block_name = block_name.replace("hollow_", "")
block_model_data = {
"parent": "block/hollow_log",
"textures": {
"top": texture_end,
"side": texture_side,
"inner": texture_inner
}
}
else:
block_model_data = {
"parent": "block/log",
"textures": {
"top": texture_end,
"side": texture_side
}
}
with open(block_model_file, "w") as f:
dumpJson(block_model_data, f)
def generateItemModel(mod_namespace, block_name):
# Create models folder if it doesn't exist already
if not os.path.exists("assets/{}/models/item/".format(mod_namespace)):
os.makedirs("assets/{}/models/item/".format(mod_namespace))
item_model_file = f"assets/{mod_namespace}/models/item/{block_name}.json"
item_model_data = {
"parent": f"{mod_namespace}:block/{block_name}1"
}
with open(item_model_file, "w") as f:
dumpJson(item_model_data, f)
def writeMetadata(args):
edition = args.edition
if isinstance(edition, list): edition = " ".join(args.edition)
with open("./input/pack.mcmeta") as infile, open("pack.mcmeta", "w") as outfile:
for line in infile:
line = line.replace("${version}", args.version).replace("${edition}", edition).replace("${year}", str(time.localtime().tm_year))
outfile.write(line)
# See https://stackoverflow.com/a/1855118
def zipdir(path, ziph):
# ziph is zipfile handle
for root, dirs, files in os.walk(path):
for file in files:
ziph.write(os.path.join(root, file),
os.path.relpath(os.path.join(root, file),
os.path.join(path, '..')))
def makeZip(filename):
with zipfile.ZipFile(filename, 'w', zipfile.ZIP_DEFLATED, compresslevel=9) as zipf:
zipdir('assets/', zipf)
zipf.write('pack.mcmeta')
zipf.write('pack.png')
zipf.write('LICENSE')
zipf.write('README.md')
# This is the main entry point, executed when the script is run
if __name__ == '__main__':
start_time = time.perf_counter()
parser = argparse.ArgumentParser(
description='This script can automatically generate files for the Round Trees resourcepack.',
epilog='Feel free to ask for help at http://discord.midnightdust.eu/')
parser.add_argument('version', type=str)
parser.add_argument('edition', nargs="*", type=str, default="", help="Define your edition name")
parser.add_argument('--minify', '-m', action='store_true', help="Minify all JSON output files")
args = parser.parse_args()
print(args)
print()
if args.minify: src.json_utils.minify = True
# Loads overrides from the json file
f = open('./input/overrides.json')
data = json.load(f)
f.close()
autoGen(data, args);
writeMetadata(args)
print()
print("Zipping it up...")
makeZip(f"Round-Trees-{args.version}.zip");
print("Done!")
print("--- Finished in %s seconds ---" % (round((time.perf_counter() - start_time)*1000)/1000))