Skip to content

Commit

Permalink
Merge pull request #3 from HappiePlant/clean-up
Browse files Browse the repository at this point in the history
Clean up the code
  • Loading branch information
HappiePlant authored Aug 24, 2024
2 parents 86320c3 + 26bb05d commit c878945
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 80 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This project aims to be 100% faithful to the original Minecraft font by providin
1. Clone this repo
2. Run `uv run src/minecraft_seven/__init__.py`
3. Open [Pixel Font Converter](https://yal.cc/r/20/pixelfont/)
4. Click `Menu` in the top right and select `Batch process`
4. Click `Menu` on the upper left and select `Batch process`
5. Navigate to the `out` folder in this repo and select both the `png` and `json` file. (by holding <kbd>Ctrl</kbd>)
6. Install the ttf in the downloaded zip!

Expand Down
5 changes: 1 addition & 4 deletions resources/1.21.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
[tileset]
tile_width = 9
tile_height = 12
tile_baseline = 10
[output]
tileset_width = 21717

[providers."minecraft:font/ascii.png"]
Expand Down
11 changes: 8 additions & 3 deletions src/minecraft_seven/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
import os
from zipfile import ZipFile
from xdialog import open_file
from minecraft_seven.builder import build_as_pixel_font_converter_batch
from minecraft_seven.builder import build_font_assets
import json

from minecraft_seven.pixel_font_exporter import export_to_pixel_font_converter_batch

MINECRAFT_VERSION = "1.21"


Expand Down Expand Up @@ -36,11 +38,14 @@ def check_minecraft_version(jar_path: str):


def main() -> None:
print("Getting jar file...")
jar_path = get_jar_path()
check_minecraft_version(jar_path)
build_as_pixel_font_converter_batch(jar_path, MINECRAFT_VERSION)

return
tileset, glyphs, dimensions = build_font_assets(jar_path, MINECRAFT_VERSION)

print("Exporting...")
export_to_pixel_font_converter_batch(tileset, glyphs, dimensions)


if __name__ == "__main__":
Expand Down
169 changes: 97 additions & 72 deletions src/minecraft_seven/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
from PIL import Image, ImageDraw


type MinecraftClientJar = ZipFile


class Provider:
id: str
file: bytes
Expand All @@ -14,39 +17,74 @@ class Provider:
chars: list[str]


def get_assets(jar_path: str, tile_data: dict) -> (list[Provider], int):
class OutputDimensions:
tile_width: int
tile_height: int
tile_baseline: int
space_width: int
tileset_width: int


def get_space_width(jar: MinecraftClientJar):
space_data: dict = json.loads(jar.read("assets/minecraft/font/include/space.json"))
return space_data["providers"][0]["advances"][" "]


def get_font_data(jar: MinecraftClientJar):
return json.loads(jar.read("assets/minecraft/font/include/default.json"))


def get_assets(
jar_path: str, dimensions: dict
) -> tuple[list[Provider], OutputDimensions]:
out = OutputDimensions()
out.tileset_width = dimensions["output"]["tileset_width"]

with ZipFile(jar_path, "r") as jar:
default_data: dict = json.loads(
jar.read("assets/minecraft/font/include/default.json")
)
space_data: dict = json.loads(
jar.read("assets/minecraft/font/include/space.json")
)
space_width = space_data["providers"][0]["advances"][" "]
providers: list[dict] = default_data["providers"]
font_data = get_font_data(jar)
providers: list[dict] = font_data["providers"]
new_providers: list[Provider] = []
out.tile_width = 0
out.tile_height = 0
out.tile_baseline = 0

for provider in providers:
new_provider: Provider = Provider()
texture_id: str = provider["file"]
new_provider.id = texture_id
texture_name = texture_id.replace(
"minecraft:", "assets/minecraft/textures/"
provider_dimensions = dimensions["providers"][provider["file"]]
new_provider = map_provider_json_to_class(
jar, provider, provider_dimensions
)
new_provider.file = jar.read(texture_name)

provider_tile_data = tile_data["providers"][texture_id]
new_provider.width = provider_tile_data["width"]
new_provider.height = provider_tile_data["height"]

new_provider.chars = provider["chars"]
new_provider.baseline = provider["ascent"]
if new_provider.width > out.tile_width:
out.tile_width = new_provider.width
if new_provider.height > out.tile_height:
out.tile_height = new_provider.height
out.tile_baseline = new_provider.baseline

new_providers.append(new_provider)

return new_providers, space_width
out.space_width = get_space_width(jar)

return new_providers, out


def load_tile_data(mc_version: str) -> dict:
def map_provider_json_to_class(jar: MinecraftClientJar, provider, provider_dimensions):
new_provider: Provider = Provider()

texture_id: str = provider["file"]
new_provider.id = texture_id

texture_name = texture_id.replace("minecraft:", "assets/minecraft/textures/")
new_provider.file = jar.read(texture_name)

new_provider.chars = provider["chars"]
new_provider.baseline = provider["ascent"]
new_provider.width = provider_dimensions["width"]
new_provider.height = provider_dimensions["height"]

return new_provider


def load_dimensions(mc_version: str) -> dict:
filename = "resources/" + mc_version + ".toml"
with open(filename, "r") as file:
return tomllib.loads(file.read())
Expand All @@ -60,70 +98,57 @@ def create_space_tile(width: int, height: int, space_width: int) -> Image:


def build_tileset(
tileset_data: dict, providers: list[Provider], space_width: int
) -> (Image, str):
tile_width = tileset_data["tile_width"]
tile_height = tileset_data["tile_height"]
tile_baseline = tileset_data["tile_baseline"]
tileset_width = tileset_data["tileset_width"]

tileset = Image.new("RGBA", (tileset_width, tile_height), color=(255, 0, 0, 0))
providers: list[Provider], out: OutputDimensions
) -> tuple[Image, str]:
tileset = Image.new(
"RGBA", (out.tileset_width, out.tile_height), color=(255, 0, 0, 0)
)
glyphs: str = ""
tileset_x = 0

for provider in providers:
char_height = provider.height
char_width = provider.width
char_baseline = provider.baseline
tile_height_offset = tile_baseline - char_baseline
tile_height_offset = out.tile_baseline - provider.baseline

font_img = Image.open(io.BytesIO(provider.file))
font_x = font_y = 0
for chars in provider.chars: # "abcdefghij"
for char in chars: # "a"
if char != "\x00":
print(char)
if char != " ":
char_img = font_img.crop(
(font_x, font_y, font_x + char_width, font_y + char_height)
if char == "\x00":
break

if char == " ":
char_img = create_space_tile(
provider.width, provider.height, out.space_width
)
else:
char_img = font_img.crop(
(
font_x,
font_y,
font_x + provider.width,
font_y + provider.height,
)
else:
char_img = create_space_tile(
char_width, char_height, space_width
)
tileset.paste(char_img, (tileset_x, tile_height_offset))
glyphs += char
)
tileset.paste(char_img, (tileset_x, tile_height_offset))
glyphs += char
tileset_x += out.tile_width
font_x += provider.width

tileset_x += tile_width
font_x += char_width
# Start at 0 at next row
font_x = 0
font_y += char_height
font_y += provider.height

return tileset, glyphs


def convert_to_pixel_font_converter_batch(
tileset: Image, glyphs: str, tileset_data: dict
):
with open("resources/pixel_font_converter_settings.json") as settings_file:
settings = json.load(settings_file)

settings["glyph-width"] = tileset_data["tile_width"]
settings["glyph-height"] = tileset_data["tile_height"]
settings["glyph-baseline"] = tileset_data["tile_baseline"]

settings["in-glyphs"] = [glyphs]
def build_font_assets(
jar_path: str, mc_version: str
) -> tuple[Image, str, OutputDimensions]:
print("Getting assets...")
dimensions = load_dimensions(mc_version)
providers, output_dimensions = get_assets(jar_path, dimensions)

with open("out/Minecraft Seven.json", "w") as settings_output_file:
json.dump(settings, settings_output_file)
print("Building tileset...")
tileset, glyphs = build_tileset(providers, output_dimensions)

tileset.save("out/Minecraft Seven.png")


def build_as_pixel_font_converter_batch(jar_path: str, mc_version: str):
tile_data = load_tile_data(mc_version)
providers, space_width = get_assets(jar_path, tile_data)
for provider in providers:
print(provider.id)
tileset, glyphs = build_tileset(tile_data["tileset"], providers, space_width)
convert_to_pixel_font_converter_batch(tileset, glyphs, tile_data["tileset"])
return tileset, glyphs, output_dimensions
47 changes: 47 additions & 0 deletions src/minecraft_seven/pixel_font_exporter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import json

from PIL import Image

from minecraft_seven.builder import OutputDimensions


def export_to_pixel_font_converter_batch(
tileset: Image, glyphs: str, out: OutputDimensions
):
with open("resources/pixel_font_converter_settings.json") as settings_file:
settings = json.load(settings_file)

settings["glyph-width"] = out.tile_width
settings["glyph-height"] = out.tile_height
settings["glyph-baseline"] = out.tile_baseline

settings["in-glyphs"] = [glyphs]

with open("out/Minecraft Seven.json", "w") as settings_output_file:
json.dump(settings, settings_output_file)

tileset.save("out/Minecraft Seven.png")

show_done_msg()


def show_done_msg():
print(f"""
Done!
1. Go to {link("https://yal.cc/r/20/pixelfont/", "[🔗 Pixel Font Converter]")}
2. Click `Menu` on the upper left and select `Batch process`
3. Navigate to the `out` folder in this repo and select both the `png` and `json` file. (by holding `Ctrl`)
4. Install the ttf in the downloaded zip!
""")


def link(uri: str, label: str = None):
if label is None:
label = uri
parameters = ""

# OSC 8 ; params ; URI ST <name> OSC 8 ;; ST
escape_mask = "\033]8;{};{}\033\\{}\033]8;;\033\\"

return escape_mask.format(parameters, uri, label)

0 comments on commit c878945

Please sign in to comment.