2017-07-19 22:44:43 +02:00
|
|
|
#!/usr/bin/env python
|
2017-07-28 04:56:49 +02:00
|
|
|
# EXPERIMENTAL texture pack copying utility.
|
2017-07-19 22:44:43 +02:00
|
|
|
# This Python script helps in converting Minecraft texture packs. It has 2 main features:
|
2017-07-28 04:56:49 +02:00
|
|
|
# - Can create a Minetest texture pack (default)
|
2017-07-19 22:44:43 +02:00
|
|
|
# - Can update the MineClone 2 textures
|
|
|
|
# This script is currently incomplete, not all textures are converted.
|
|
|
|
#
|
|
|
|
# Requirements:
|
|
|
|
# - Python 3
|
|
|
|
# - Python Library: Pillow
|
|
|
|
# - ImageMagick
|
|
|
|
#
|
|
|
|
# Usage (to be simplified later):
|
|
|
|
# - Put extracted texture pack into $HOME/tmp/pp
|
2017-11-18 03:42:44 +01:00
|
|
|
# - Make sure the file “Conversion_Table.csv” is in the same directory as the script
|
2017-07-19 22:44:43 +02:00
|
|
|
# - Run the script in its directory
|
2017-11-18 02:33:43 +01:00
|
|
|
# - If everything worked, retrieve texture pack in New_MineClone_2_Texture_Pack/
|
2017-07-19 22:44:43 +02:00
|
|
|
|
|
|
|
__author__ = "Wuzzy"
|
2017-11-18 01:25:55 +01:00
|
|
|
__license__ = "MIT License"
|
2017-07-19 22:44:43 +02:00
|
|
|
__status__ = "Development"
|
|
|
|
|
2017-11-18 02:33:43 +01:00
|
|
|
import shutil, csv, os, tempfile, sys, getopt
|
|
|
|
from PIL import Image
|
|
|
|
|
|
|
|
# Helper vars
|
|
|
|
home = os.environ["HOME"]
|
|
|
|
mineclone2_path = home + "/.minetest/games/mineclone2"
|
|
|
|
working_dir = os.getcwd()
|
|
|
|
output_dir_name = "New_MineClone_2_Texture_Pack"
|
2017-11-18 03:42:44 +01:00
|
|
|
appname = "Texture_Converter.py"
|
2017-11-18 02:33:43 +01:00
|
|
|
|
2017-07-19 22:44:43 +02:00
|
|
|
### SETTINGS ###
|
2017-11-18 02:33:43 +01:00
|
|
|
output_dir = working_dir
|
|
|
|
|
|
|
|
base_dir = None
|
|
|
|
|
2017-07-19 22:44:43 +02:00
|
|
|
# If True, will only make console output but not convert anything.
|
|
|
|
dry_run = False
|
|
|
|
|
|
|
|
# If True, textures will be put into a texture pack directory structure.
|
|
|
|
# If False, textures will be put into MineClone 2 directories.
|
2017-07-28 04:56:49 +02:00
|
|
|
make_texture_pack = True
|
2017-07-19 22:44:43 +02:00
|
|
|
|
2017-07-28 14:36:50 +02:00
|
|
|
# If True, prints all copying actions
|
|
|
|
verbose = False
|
|
|
|
|
2017-11-18 03:40:29 +01:00
|
|
|
PXSIZE = 16
|
|
|
|
|
2017-11-18 03:42:44 +01:00
|
|
|
syntax_help = appname+""" -i <input dir> [-o <output dir>] [-d] [-v|-q] [-h]
|
2017-11-18 02:33:43 +01:00
|
|
|
Mandatory argument:
|
|
|
|
-i <input directory>
|
|
|
|
Directory of Minecraft resource pack to convert
|
|
|
|
|
|
|
|
Optional arguments:
|
2017-11-18 03:40:29 +01:00
|
|
|
-p <size>
|
|
|
|
Specify the size of the original textures (default: 16)
|
2017-11-18 02:33:43 +01:00
|
|
|
-o <output directory>
|
|
|
|
Directory in which to put the resulting MineClone 2 texture pack
|
|
|
|
(default: working directory)
|
|
|
|
-d
|
|
|
|
The script will only pretend to convert textures by writing
|
|
|
|
to the console only, but not changing any files.
|
|
|
|
-v
|
|
|
|
Prints out all copying actions
|
|
|
|
-h
|
|
|
|
Shows this help an exits"""
|
|
|
|
try:
|
2017-11-18 03:40:29 +01:00
|
|
|
opts, args = getopt.getopt(sys.argv[1:],"hi:o:p:dv")
|
2017-11-18 02:33:43 +01:00
|
|
|
except getopt.GetoptError:
|
|
|
|
print(
|
|
|
|
"""ERROR! The options you gave me make no sense!
|
|
|
|
|
|
|
|
Here's the syntax reference:""")
|
|
|
|
print(syntax_help)
|
|
|
|
sys.exit(2)
|
|
|
|
for opt, arg in opts:
|
|
|
|
if opt == "-h":
|
|
|
|
print(
|
|
|
|
"""This is the official MineClone 2 Texture Converter.
|
|
|
|
This will convert textures from Minecraft resource packs to
|
|
|
|
a MineClone 2 texture pack.
|
|
|
|
|
|
|
|
Supported Minecraft version: 1.12 (Java Edition)
|
|
|
|
|
|
|
|
Syntax:""")
|
|
|
|
print(syntax_help)
|
|
|
|
sys.exit()
|
|
|
|
elif opt == "-d":
|
|
|
|
dry_run = True
|
|
|
|
elif opt == "-v":
|
|
|
|
verbose = True
|
|
|
|
elif opt == "-i":
|
|
|
|
base_dir = arg
|
|
|
|
elif opt == "-o":
|
|
|
|
output_dir = arg
|
2017-11-18 03:40:29 +01:00
|
|
|
elif opt == "-p":
|
|
|
|
PXSIZE = int(arg)
|
2017-11-18 02:33:43 +01:00
|
|
|
|
|
|
|
if base_dir == None:
|
|
|
|
print(
|
|
|
|
"""ERROR: You forgot to tell me the path to the Minecraft resource pack.
|
|
|
|
Mind-reading has not been implemented yet.
|
|
|
|
|
|
|
|
Try this:
|
2017-11-18 03:42:44 +01:00
|
|
|
"""+appname+""" -i <path to resource pack>
|
2017-11-18 02:33:43 +01:00
|
|
|
|
|
|
|
For the full help, use:
|
2017-11-18 03:42:44 +01:00
|
|
|
"""+appname+""" -h""")
|
2017-11-18 02:33:43 +01:00
|
|
|
sys.exit(2);
|
2017-07-19 22:44:43 +02:00
|
|
|
|
2017-11-18 02:33:43 +01:00
|
|
|
### END OF SETTINGS ###
|
2017-07-19 22:44:43 +02:00
|
|
|
|
|
|
|
tex_dir = base_dir + "/assets/minecraft/textures"
|
|
|
|
|
2017-07-28 14:20:50 +02:00
|
|
|
# FUNCTION DEFINITIONS
|
|
|
|
|
2017-11-18 05:52:40 +01:00
|
|
|
def convert_alphatex(colormap, source, colormap_pixel, texture_size, destination):
|
|
|
|
os.system("convert "+colormap+" -crop 1x1+"+colormap_pixel+" -depth 8 -resize "+texture_size+"x"+texture_size+" "+tempfile1.name)
|
|
|
|
os.system("composite -compose Multiply "+tempfile1.name+" "+source+" "+tempfile2.name)
|
2017-11-18 06:13:08 +01:00
|
|
|
os.system("composite -compose Dst_In "+source+" "+tempfile2.name+" -alpha Set "+destination)
|
2017-07-19 22:44:43 +02:00
|
|
|
|
|
|
|
def target_dir(directory):
|
|
|
|
if make_texture_pack:
|
2017-11-18 02:33:43 +01:00
|
|
|
return output_dir + "/" + output_dir_name
|
2017-07-19 22:44:43 +02:00
|
|
|
else:
|
|
|
|
return mineclone2_path + directory
|
|
|
|
|
|
|
|
# Copy texture files
|
|
|
|
def convert_textures():
|
2017-07-28 14:36:50 +02:00
|
|
|
failed_conversions = 0
|
|
|
|
print("Texture conversion BEGINS NOW!")
|
2017-11-18 03:42:44 +01:00
|
|
|
with open("Conversion_Table.csv", newline="") as csvfile:
|
2017-07-19 22:44:43 +02:00
|
|
|
reader = csv.reader(csvfile, delimiter=",", quotechar='"')
|
|
|
|
first_row = True
|
|
|
|
for row in reader:
|
|
|
|
# Skip first row
|
|
|
|
if first_row:
|
|
|
|
first_row = False
|
|
|
|
continue
|
|
|
|
|
|
|
|
src_dir = row[0]
|
|
|
|
src_filename = row[1]
|
|
|
|
dst_dir = row[2]
|
|
|
|
dst_filename = row[3]
|
|
|
|
if row[4] != "":
|
|
|
|
xs = int(row[4])
|
|
|
|
ys = int(row[5])
|
|
|
|
xl = int(row[6])
|
|
|
|
yl = int(row[7])
|
|
|
|
xt = int(row[8])
|
|
|
|
yt = int(row[9])
|
|
|
|
else:
|
|
|
|
xs = None
|
2017-11-18 04:42:42 +01:00
|
|
|
blacklisted = row[10]
|
|
|
|
|
|
|
|
if blacklisted == "y":
|
|
|
|
# Skip blacklisted files
|
|
|
|
continue
|
2017-07-19 22:44:43 +02:00
|
|
|
|
|
|
|
src_file = base_dir + src_dir + "/" + src_filename # source file
|
|
|
|
src_file_exists = os.path.isfile(src_file)
|
|
|
|
dst_file = target_dir(dst_dir) + "/" + dst_filename # destination file
|
|
|
|
|
|
|
|
if src_file_exists == False:
|
|
|
|
print("WARNING: Source file does not exist: "+src_file)
|
2017-07-28 14:36:50 +02:00
|
|
|
failed_conversions = failed_conversions + 1
|
2017-07-19 22:44:43 +02:00
|
|
|
continue
|
|
|
|
|
|
|
|
if xs != None:
|
|
|
|
# Crop and copy images
|
|
|
|
image = Image.open(src_file)
|
|
|
|
if not dry_run:
|
|
|
|
region = image.crop((xs, ys, xs+xl, ys+yl))
|
|
|
|
region.load()
|
|
|
|
region.save(dst_file)
|
2017-07-28 14:36:50 +02:00
|
|
|
if verbose:
|
|
|
|
print(src_file + " → " + dst_file)
|
2017-07-19 22:44:43 +02:00
|
|
|
else:
|
|
|
|
# Copy image verbatim
|
|
|
|
if not dry_run:
|
|
|
|
shutil.copy2(src_file, dst_file)
|
2017-07-28 14:36:50 +02:00
|
|
|
if verbose:
|
|
|
|
print(src_file + " → " + dst_file)
|
2017-07-19 22:44:43 +02:00
|
|
|
|
|
|
|
# Convert chest textures (requires ImageMagick)
|
|
|
|
chest_file = tex_dir + "/entity/chest/normal.png"
|
|
|
|
|
|
|
|
if os.path.isfile(chest_file):
|
|
|
|
CHPX=((PXSIZE / 16 * 14)) # Chests in MC are 2/16 smaller!
|
2017-11-18 04:42:42 +01:00
|
|
|
# Chests are currently blacklisted
|
2017-07-19 22:44:43 +02:00
|
|
|
|
2017-11-18 04:42:42 +01:00
|
|
|
# os.system("convert " + chest_file + " \
|
|
|
|
#\( -clone 0 -crop "+str(CHPX)+"x"+str(CHPX)+"+"+str(CHPX)+"+0 \) -geometry +0+0 -composite -extent "+str(CHPX)+"x"+str(CHPX)+" "+target_dir("/mods/ITEMS/mcl_chests/textures")+"/default_chest_top.png")
|
2017-07-19 22:44:43 +02:00
|
|
|
|
2017-11-18 04:42:42 +01:00
|
|
|
# os.system("convert " + chest_file + " \
|
|
|
|
#\( -clone 0 -crop "+str(CHPX)+"x"+str((PXSIZE/16)*5)+"+"+str(CHPX)+"+"+str(CHPX)+" \) -geometry +0+0 -composite \
|
|
|
|
#\( -clone 0 -crop "+str(CHPX)+"x"+str((PXSIZE/16)*10)+"+"+str(CHPX)+"+"+str((2*CHPX) + ((PXSIZE/16)*5))+" \) -geometry +0+"+str((PXSIZE/16)*5)+" -composite \
|
|
|
|
#-extent "+str(CHPX)+"x"+str(CHPX)+" "+target_dir("/mods/ITEMS/mcl_chests/textures")+"/default_chest_front.png")
|
2017-07-19 22:44:43 +02:00
|
|
|
|
2017-07-26 23:34:06 +02:00
|
|
|
# TODO: Convert other chest sides
|
2017-07-19 22:44:43 +02:00
|
|
|
|
|
|
|
# Convert grass
|
|
|
|
grass_file = tex_dir + "/blocks/grass_top.png"
|
|
|
|
if os.path.isfile(grass_file):
|
|
|
|
FOLIAG = tex_dir+"/colormap/foliage.png"
|
|
|
|
GRASS = tex_dir+"/colormap/grass.png"
|
|
|
|
|
|
|
|
|
|
|
|
# Leaves
|
2017-11-18 07:16:06 +01:00
|
|
|
convert_alphatex(FOLIAG, tex_dir+"/blocks/leaves_oak.png", "116+143", str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/default_leaves.png")
|
|
|
|
convert_alphatex(FOLIAG, tex_dir+"/blocks/leaves_big_oak.png", "158+177", str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/mcl_core_leaves_big_oak.png")
|
|
|
|
convert_alphatex(FOLIAG, tex_dir+"/blocks/leaves_acacia.png", "40+255", str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/default_acacia_leaves.png")
|
|
|
|
convert_alphatex(FOLIAG, tex_dir+"/blocks/leaves_spruce.png", "226+230", str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/mcl_core_leaves_spruce.png")
|
|
|
|
convert_alphatex(FOLIAG, tex_dir+"/blocks/leaves_birch.png", "141+186", str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/mcl_core_leaves_birch.png")
|
|
|
|
convert_alphatex(FOLIAG, tex_dir+"/blocks/leaves_jungle.png", "16+39", str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/default_jungleleaves.png")
|
2017-07-19 22:44:43 +02:00
|
|
|
|
|
|
|
# Waterlily
|
2017-11-18 07:16:06 +01:00
|
|
|
convert_alphatex(FOLIAG, tex_dir+"/blocks/waterlily.png", "16+39", str(PXSIZE), target_dir("/mods/ITEMS/mcl_flowers/textures")+"/flowers_waterlily.png")
|
2017-07-19 22:44:43 +02:00
|
|
|
|
|
|
|
# Vines
|
2017-11-18 07:16:06 +01:00
|
|
|
convert_alphatex(FOLIAG, tex_dir+"/blocks/vine.png", "16+39", str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/mcl_core_vine.png")
|
2017-07-19 22:44:43 +02:00
|
|
|
|
2017-11-16 03:13:19 +01:00
|
|
|
# Tall grass, fern (inventory images)
|
2017-11-18 07:16:06 +01:00
|
|
|
pcol = "49+172" # Plains grass color
|
|
|
|
convert_alphatex(GRASS, tex_dir+"/blocks/tallgrass.png", pcol, str(PXSIZE), target_dir("/mods/ITEMS/mcl_flowers/textures")+"/mcl_flowers_tallgrass_inv.png")
|
|
|
|
convert_alphatex(GRASS, tex_dir+"/blocks/fern.png", pcol, str(PXSIZE), target_dir("/mods/ITEMS/mcl_flowers/textures")+"/mcl_flowers_fern_inv.png")
|
|
|
|
convert_alphatex(GRASS, tex_dir+"/blocks/double_plant_fern_top.png", pcol, str(PXSIZE), target_dir("/mods/ITEMS/mcl_flowers/textures")+"/mcl_flowers_double_plant_fern_inv.png")
|
|
|
|
convert_alphatex(GRASS, tex_dir+"/blocks/double_plant_grass_top.png", pcol, str(PXSIZE), target_dir("/mods/ITEMS/mcl_flowers/textures")+"/mcl_flowers_double_plant_grass_inv.png")
|
2017-11-16 03:13:19 +01:00
|
|
|
|
|
|
|
# TODO: Convert grass palette
|
|
|
|
|
2017-11-14 23:44:53 +01:00
|
|
|
offset = [
|
2017-11-18 07:16:06 +01:00
|
|
|
[ pcol, "", "grass" ], # Default grass: Plains
|
|
|
|
[ "40+255", "_dry", "dry_grass" ], # Dry grass: Savanna, Mesa Plateau F, Nether, …
|
2017-11-14 23:44:53 +01:00
|
|
|
]
|
|
|
|
for o in offset:
|
|
|
|
|
|
|
|
os.system("convert "+GRASS+" -crop 1x1+"+o[0]+" -depth 8 -resize "+str(PXSIZE)+"x"+str(PXSIZE)+" "+tempfile1.name)
|
|
|
|
os.system("composite -compose Multiply "+tempfile1.name+" "+tex_dir+"/blocks/grass_top.png "+target_dir("/mods/ITEMS/mcl_core/textures")+"/default_"+o[2]+".png")
|
|
|
|
convert_alphatex(GRASS, tex_dir+"/blocks/grass_side_overlay.png", o[0], str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/default_"+o[2]+"_side.png")
|
|
|
|
|
|
|
|
|
2017-07-19 22:44:43 +02:00
|
|
|
|
2017-07-28 01:42:25 +02:00
|
|
|
# TODO: Convert banner masks
|
|
|
|
# if os.path.isdir(tex_dir + "/entity/banner"):
|
|
|
|
# These are the ImageMagick commands needed to convert the mask images
|
|
|
|
# os.system("mogrify -transparent-color "+filename)
|
|
|
|
# os.system("mogrify -clip-mask "+tex_dir+"/entity/banner/base.png"+" -alpha Copy "+filename)
|
|
|
|
# os.system("mogrify -fill white -colorize 100 "+filename)
|
|
|
|
|
2017-07-28 14:29:15 +02:00
|
|
|
print("Textures conversion COMPLETE!")
|
2017-07-28 14:36:50 +02:00
|
|
|
if failed_conversions > 0:
|
2017-07-28 14:41:02 +02:00
|
|
|
print("WARNING: Number of missing files in original resource pack: "+str(failed_conversions))
|
|
|
|
print("NOTE: Please keep in mind this script does not reliably convert all the textures yet.")
|
2017-07-28 14:29:15 +02:00
|
|
|
if make_texture_pack:
|
2017-11-18 02:33:43 +01:00
|
|
|
print("You can now retrieve the texture pack in "+output_dir+"/"+output_dir_name+"/")
|
2017-07-19 22:44:43 +02:00
|
|
|
|
2017-07-28 14:20:50 +02:00
|
|
|
# ENTRY POINT
|
2017-11-18 02:33:43 +01:00
|
|
|
if make_texture_pack and not os.path.isdir(output_dir+"/"+output_dir_name):
|
|
|
|
os.mkdir(output_dir+"/"+output_dir_name)
|
2017-07-28 14:20:50 +02:00
|
|
|
|
|
|
|
tempfile1 = tempfile.NamedTemporaryFile()
|
|
|
|
tempfile2 = tempfile.NamedTemporaryFile()
|
|
|
|
|
2017-07-19 22:44:43 +02:00
|
|
|
convert_textures()
|
2017-07-28 14:20:50 +02:00
|
|
|
|
|
|
|
tempfile1.close()
|
|
|
|
tempfile2.close()
|