Code:
import os
import shutil
import subprocess
import struct
import csv
def get_more_xmodels(filename):
found = []
if os.path.exists(filename):
f = open(filename, "r")
for line in f:
if len(line) != 0:
found.append(line.strip('\n').strip('\r'))
return found
def get_more_materials(filename):
found = []
if os.path.exists(filename):
f = open(filename, "r")
for line in f:
if len(line) != 0:
found.append(line.strip('\n').strip('\r'))
return found
def get_weapon_xmodels(filename):
found = []
models = []
if os.path.exists(filename):
f = open(filename, "r")
for line in f:
if len(line) != 0:
found.append(line.strip('\n').strip('\r'))
for weap in found:
if os.path.exists(os.path.join(source_stock, "weapons", "mp", weap)):
continue
if os.path.exists(os.path.join(source, "weapons", "mp", weap)):
with open(os.path.join(source, "weapons", "mp", weap)) as weapfile:
reader = csv.reader(weapfile, delimiter = "\\")
num = 0
next_is_model = False
for row in reader:
for elem in row:
num += 1
if next_is_model:
next_is_model = False
if "xmodel/" in elem:
models.append(elem)
else:
models.append("xmodel/" + elem)
elif "model" in elem.lower() and not num%2:
next_is_model = True
else:
next_is_model = False
else:
print("weapon not found:", weap, "for map:", filename)
return models
def get_weapon_materials(filename):
found = []
materials = []
if os.path.exists(filename):
f = open(filename, "r")
for line in f:
if len(line) != 0:
found.append(line.strip('\n').strip('\r'))
for weap in found:
if os.path.exists(os.path.join(source_stock, "weapons", "mp", weap)):
continue
if os.path.exists(os.path.join(source, "weapons", "mp", weap)):
with open(os.path.join(source, "weapons", "mp", weap)) as weapfile:
reader = csv.reader(weapfile, delimiter = "\\")
num = 0
next_is_material = False
for row in reader:
for elem in row:
num += 1
if next_is_material:
next_is_material = False
materials.append(elem)
elif "icon" in elem and not num%2:
next_is_material = True
else:
next_is_material = False
else:
print("weapon not found:", weap, "for map:", filename)
return materials
def get_xmodels(filename):
models = []
f = open(filename, "rb")
for line in f:
if line.startswith(bytes(r'"model"', "utf-8")):
#print(line)
strs = ""
start = False
for chars in line:
if chr(chars) == " ":
start = True
elif chr(chars) == "\n":
break
elif start and chr(chars) == "*":
break;
elif start and chr(chars) != "\"":
strs += chr(chars)
if len(strs):
if not strs in models:
models.append(strs)
return models
def getxmodelparts(filename, mapname):
parts = []
f = open(filename, "rb")
res = f.read(1)
pos = 1
startpos = -1
count_255 = 0
while len(res) == 1:
if res[0] == 0:
count_255 += 1
if count_255 == 4:
if startpos == -1:
startpos = pos
else:
count_255 = 0
res = f.read(1)
pos += 1
f.close()
f = open(filename, "rb")
if startpos >= 1:
f.read(startpos)
else:
f.close()
print("bad stuff happened for part", filename, mapname)
return parts
char = f.read(1)
pos = 1
strs = ""
while pos <= 32:
if char == b"\x00":
break;
strs += char.decode("utf-8")
char = f.read(1)
pos += 1
f.close()
parts.append(strs)
return parts
def getmaterialsxmodel(filename, mapname):
mats = []
f = open(filename, "rb")
res = f.read(1)
pos = 1
startpos = -1
count_255 = 0
while len(res) == 1:
if res[0] == 255:
count_255 += 1
if count_255 == 4:
if startpos == -1:
startpos = pos
else:
count_255 = 0
res = f.read(1)
pos += 1
f.close()
f = open(filename, "rb")
if startpos >= 0:
f.read(startpos + 4)
else:
f.close()
print("bad stuff happened for materialfind ", filename, mapname)
return mats
count = 0
count += int(f.read(1)[0])
count += int(f.read(1)[0]) * 256
char = f.read(1)
strs = ""
while len(char) == 1 and len(mats) < count:
if char == b"\x00":
mats.append(strs)
strs = ""
else:
strs += char.decode("utf-8")
char = f.read(1)
f.close()
return mats
def get_loadscreen(filename):
mats = []
if not os.path.exists(filename):
return mats
with open(filename) as csvfile:
reader = csv.reader(csvfile, delimiter = ",")
for row in reader:
if len(row) < 2:
continue
if len(row) == 2 and row[0].lower() == "levelbriefing":
mats.append(row[1])
else:
print("bad stuff:", filename, row[0], row[1])
return mats
def get_sounds(mapname):
files = []
if not os.path.exists(os.path.join(source, "soundaliases", mapname + ".csv")):
return files
with open(os.path.join(source, "soundaliases", mapname + ".csv")) as csvfile:
file_index = -1
loadspec_index = -1
name_index = -1
reader = csv.reader(csvfile, delimiter = ",")
linenum = 0
for row in reader:
linenum += 1
if len(row) < 3:
continue
if row[0].startswith(r",") or row[0].startswith(r"#") or row[0].startswith(r"\"") or len(row[0]) == 0:
continue
if file_index == -1 and "file" in row:
file_index = row.index("file")
if loadspec_index == -1 and "loadspec" in row:
loadspec_index = row.index("loadspec")
if name_index == -1 and "name" in row:
name_index = row.index("name")
continue
if file_index == -1 or loadspec_index == -1:
continue
if name_index != -1 and len(row) > name_index and row[name_index] == "null":
continue
if len(row) <= loadspec_index or loadspec_index == -1:
print(mapname, "has loadspec out-of-bounds for", row[0])
elif row[loadspec_index] != mapname:
print(mapname, "has invalid loadspec for", row[0])
files.append(row[file_index])
return files
def get_materials(filename):
f = open(filename, "rb")
data = f.read(8)
l = f.read(4)
total_l = 0
multi = 1
for e in l:
total_l += int(e) * multi
multi *= 256
o = f.read(4)
total_o = 0
multi = 1
for e in o:
total_o += int(e) * multi
multi *= 256
f.close()
curloc = total_o
mats = []
while (curloc < total_o + total_l):
f = open(filename, "rb");
f.read(curloc)
mat = ""
loc = curloc
while loc < curloc + 64:
r = f.read(1)
loc += 1
if r == b"\x00":
break;
mat += r.decode("utf-8")
curloc += 72
f.close()
mats.append(mat)
f.close()
return mats
def get_images(filename):
f = open(filename, "rb")
f.read(4)
o = f.read(4)
total_o = 0
multi = 1
for e in o:
total_o += int(e) * multi
multi *= 256
f.close()
mats = []
f = open(filename, "rb")
f.read(total_o)
r = f.read(1)
mat = ""
while(len(r) > 0):
if(r == b"\x00"):
if len(mat) != 0:
mats.append(mat)
mat = ""
else:
mat += r.decode("utf-8")
r = f.read(1)
f.close()
return mats
startdir = "C:/JH2"
source = os.path.join(startdir, "merged")
source_stock = os.path.join(startdir, "stock")
dest_packs = os.path.join(startdir, "packs")
dest_soundalias = os.path.join(startdir, "soundaliases")
dest_empty = os.path.join(startdir, "empty_files")
dest_filelist = os.path.join(startdir, "filelist")
source_d3dbsp = os.path.join(source, "maps", "mp")
source_add_models = os.path.join(startdir, "add_models")
source_add_shaders = os.path.join(startdir, "add_shaders")
source_add_weapons = os.path.join(startdir, "add_weapons")
if os.path.exists(dest_packs):
shutil.rmtree(dest_packs)
os.mkdir(dest_packs)
if os.path.exists(dest_empty):
shutil.rmtree(dest_empty)
os.mkdir(dest_empty)
if os.path.exists(dest_filelist):
shutil.rmtree(dest_filelist)
os.mkdir(dest_filelist)
if os.path.exists(dest_soundalias):
shutil.rmtree(dest_soundalias)
os.mkdir(dest_soundalias)
for r,d,f in os.walk(source_d3dbsp):
for files in f:
if not files.endswith(".d3dbsp"):
continue
mapname = os.path.splitext(files)[0]
#print(mapname)
if not os.path.exists(os.path.join(dest_packs, mapname)):
os.mkdir(os.path.join(dest_packs, mapname))
if not os.path.exists(os.path.join(dest_packs, mapname, "maps")):
os.mkdir(os.path.join(dest_packs, mapname, "maps"))
if not os.path.exists(os.path.join(dest_packs, mapname, "maps", "mp")):
os.mkdir(os.path.join(dest_packs, mapname, "maps", "mp"))
if not os.path.exists(os.path.join(dest_packs, mapname, "maps", "mp", mapname + ".d3dbsp")):
shutil.copy(os.path.join(source_d3dbsp, mapname + ".d3dbsp"), os.path.join(dest_packs, mapname, "maps", "mp"))
if os.path.exists(os.path.join(source_d3dbsp, mapname + ".d3dprt")) and not os.path.exists(os.path.join(dest_packs, mapname, "maps", "mp", mapname + ".d3dprt")):
shutil.copy(os.path.join(source_d3dbsp, mapname + ".d3dprt"), os.path.join(dest_packs, mapname, "maps", "mp"))
mats = get_materials(source_d3dbsp + "/" + files)
models = get_xmodels(source_d3dbsp + "/" + files)
models2 = get_more_xmodels(os.path.join(source_add_models, mapname + ".txt"))
models3 = get_weapon_xmodels(os.path.join(source_add_weapons, mapname + ".txt"))
models = models + models2 + models3
for m in models:
if os.path.exists(os.path.join(source_stock, m)):
continue
if not os.path.exists(os.path.join(source, m)):
print("Missing", m, "from map", mapname)
continue
if not os.path.exists(os.path.join(dest_packs, mapname, m)):
if not os.path.exists(os.path.dirname(os.path.join(dest_packs, mapname, m))):
os.makedirs(os.path.dirname(os.path.join(dest_packs, mapname, m)))
shutil.copy(os.path.join(source, m), os.path.dirname(os.path.join(dest_packs, mapname, m)))
mat_model = getmaterialsxmodel(source + "/" + m, mapname)
mats = mats + mat_model
xparts = getxmodelparts(source + "/" + m, mapname)
#if len(xparts) == 0:
# print("No parts in", m)
for p in xparts:
if os.path.exists(os.path.join(source_stock, "xmodelparts", p)):
#print("using stock for", p)
continue
if not os.path.exists(os.path.join(source, "xmodelparts", p)):
print("missing part", p, "for map", mapname)
continue
if not os.path.exists(os.path.join(dest_packs, mapname, "xmodelparts", p)):
if not os.path.exists(os.path.dirname(os.path.join(dest_packs, mapname, "xmodelparts", p))):
os.makedirs(os.path.dirname(os.path.join(dest_packs, mapname, "xmodelparts", p)))
shutil.copy(os.path.join(source, "xmodelparts", p), os.path.dirname(os.path.join(dest_packs, mapname, "xmodelparts", p)))
#print("copying xmodelpart", p)
#else:
# print("too lazy to copy", p)
for p in xparts:
if os.path.exists(os.path.join(source_stock, "xmodelsurfs", p)):
continue
if not os.path.exists(os.path.join(source, "xmodelsurfs", p)):
print("missing surf", p, "for map", mapname)
continue
if not os.path.exists(os.path.join(dest_packs, mapname, "xmodelsurfs", p)):
if not os.path.exists(os.path.dirname(os.path.join(dest_packs, mapname, "xmodelsurfs", p))):
os.makedirs(os.path.dirname(os.path.join(dest_packs, mapname, "xmodelsurfs", p)))
shutil.copy(os.path.join(source, "xmodelsurfs", p), os.path.dirname(os.path.join(dest_packs, mapname, "xmodelsurfs", p)))
if os.path.exists(source_d3dbsp + "/" + mapname + ".csv"):
mats_loadscreen = get_loadscreen(source_d3dbsp + "/" + mapname + ".csv")
mats = mats + mats_loadscreen
if not os.path.exists(os.path.join(dest_packs, mapname, "maps", "mp", mapname + ".csv")):
shutil.copy(os.path.join(source_d3dbsp + "/" + mapname + ".csv"), os.path.join(dest_packs, mapname, "maps", "mp"))
mats2 = get_more_materials(os.path.join(source_add_shaders, mapname + ".txt"))
mats3 = get_weapon_materials(os.path.join(source_add_weapons, mapname + ".txt"))
mats = mats + mats2
for mat in mats:
if mat == "noshader":
continue
if os.path.exists(os.path.join(source_stock, "materials", mat)):
continue
if not os.path.exists(source + "/materials/" + mat):
print("Could not find material:", mat, "from map:", mapname)
elif not os.path.exists(os.path.join(dest_packs, mapname, "materials", mat)):
if not os.path.exists(os.path.join(dest_packs, mapname, "materials")):
os.mkdir(os.path.join(dest_packs, mapname, "materials"))
shutil.copy(os.path.join(source, "materials", mat), os.path.join(dest_packs, mapname, "materials"))
imgs = get_images(os.path.join(dest_packs, mapname, "materials", mat))
for img in imgs:
if img.lower() == "colormap" or img.lower() == "detailmap" or img.lower() == "normalmap" or img.lower() == "detailscale" or img.lower() == "specularmap":
continue
if os.path.exists(os.path.join(source_stock, "images", img + ".iwi")):
continue
if not os.path.exists(os.path.join(source, "images", img + ".iwi")):
print("Could not find image:", img + ".iwi", "from map:", mapname)
elif not os.path.exists(os.path.join(dest_packs, mapname, "images", img + ".iwi")):
if not os.path.exists(os.path.join(dest_packs, mapname, "images")):
os.mkdir(os.path.join(dest_packs, mapname, "images"))
shutil.copy(os.path.join(source, "images", img + ".iwi"), os.path.join(dest_packs, mapname, "images"))
sounds = get_sounds(mapname)
if len(sounds) > 0:
if not os.path.exists(os.path.join(dest_soundalias, mapname + ".csv")):
shutil.copy(os.path.join(source, "soundaliases", mapname + ".csv"), os.path.join(dest_soundalias, mapname + ".csv"))
for sound in sounds:
if not os.path.exists(os.path.join(dest_packs, mapname, "sound", sound)):
if os.path.exists(os.path.join(source_stock, "sound", sound)):
continue
if os.path.exists(os.path.join(source, "sound", sound)):
d = os.path.dirname(os.path.join(dest_packs, mapname, "sound", sound))
if not os.path.exists(d):
os.makedirs(d)
if not os.path.exists(os.path.join(dest_packs, mapname, "sound", sound)):
shutil.copy(os.path.join(source, "sound", sound), os.path.join(dest_packs, mapname, "sound", sound))
else:
print("Could not find sound:", sound, "from map", mapname)
for subdir in os.listdir(dest_packs):
mapdir = os.path.join(dest_packs, subdir)
for src_dir, dirs, files in os.walk(mapdir):
dst_dir_empty = src_dir.replace(mapdir, dest_empty)
if not os.path.exists(dst_dir_empty):
os.mkdir(dst_dir_empty)
for file_ in files:
src_file = os.path.join(src_dir, file_)
dst_empty_file = os.path.join(dst_dir_empty, file_)
if not os.path.exists(dst_empty_file):
open(dst_empty_file, 'a').close()
for subdir in os.listdir(dest_packs):
for r,d,f in os.walk(os.path.join(dest_packs, subdir)):
for files in f:
if files.endswith(".d3dbsp"):
mapname = os.path.splitext(files)[0]
iwd = subdir
mapname = mapname.lower()
f = open(dest_filelist + "/" + mapname + ".txt", "a")
f.write(iwd + ",\n")
f.close()
input("Press enter to start the packing of the maps")
p = subprocess.Popen(os.path.join(startdir, "zip_packs.bat"), cwd=dest_packs)
stdout, stderr = p.communicate()
It works the same as the add_models/add_shaders, only now create your mapname.txt containing line-ending separated weaponnames in add_weapons folder