Files
xczjhk/_gen_box_of_nails.py
2026-10-09 18:23:57 +08:00

134 lines
4.7 KiB
Python

# -*- coding: utf-8 -*-
"""把 box_of_nails.bbmodel 转换为网易自定义方块模型(netease:block_geometry)。
转换规则(与官方 CustomBlocksMod 示例的 bbmodel->json 实测结果一致):
cube.origin = [-to.x, from.y, from.z]
cube.size = to - from
cube.pivot = [-bb.origin.x, bb.origin.y, bb.origin.z]
cube.rotation / bone.rotation = [-rx, -ry, rz]
uv: up 面 -> uv=[x2,y2], uv_size=[x1-x2, y1-y2]
其余面 -> uv=[x1,y1], uv_size=[x2-x1, y2-y1]
负的 uv_size 表示贴图镜像(与原格式一致)
贴图为空(texture=null 或零面积)的面不输出
"""
import base64
import json
import os
ROOT = r"e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\0aaaa4f2f16c46e8964025a5ab0ecc02"
RES = os.path.join(ROOT, "resource_pack_t7eJjrxY")
SRC = r"c:\Users\30272\.trae-cn\attachments\6ac7514c01a7d726cbee7358\7dc21437-b0c4-442b-a225-1ce20d2bdbbc_593d488a-acae-4a41-a007-98367aec6727_box_of_nails.bbmodel"
TEX_NAME = "box_of_nails"
TEX_KEY = "dn_sa_" + TEX_NAME
MODEL_ID = "dn_sa:" + TEX_NAME + "_model"
BONE_NAME = "bone"
FACE_ORDER = ("north", "east", "south", "west", "up", "down")
def num(v):
if isinstance(v, float):
if v.is_integer():
return int(v)
return round(v, 4)
return v
def arr(v):
return "[" + ", ".join(str(num(x)) for x in v) + "]"
def conv_uv(el):
out = []
for face in FACE_ORDER:
f = el["faces"].get(face)
if not f or f.get("texture") is None:
continue
x1, y1, x2, y2 = f["uv"]
if x1 == x2 or y1 == y2:
continue
if face == "up":
entry = "{" + '"uv": %s, "uv_size": %s' % (arr([x2, y2]), arr([x1 - x2, y1 - y2]))
else:
entry = "{" + '"uv": %s, "uv_size": %s' % (arr([x1, y1]), arr([x2 - x1, y2 - y1]))
if f.get("rotation"):
entry += ', "rot": %s' % num(f["rotation"])
entry += "}"
out.append('"%s": %s' % (face, entry))
return out
def main():
with open(SRC, "r", encoding="utf-8") as fp:
bb = json.load(fp)
tex = bb["textures"][0]
tw, th = tex["width"], tex["height"]
# 1) 贴图 -> resourcepack/textures/blocks
raw = base64.b64decode(tex["source"].split(",", 1)[1])
tex_dir = os.path.join(RES, "textures", "blocks")
os.makedirs(tex_dir, exist_ok=True)
tex_path = os.path.join(tex_dir, TEX_NAME + ".png")
with open(tex_path, "wb") as fp:
fp.write(raw)
# 2) 模型 -> resourcepack/models/netease_block
cube_blocks = []
for el in bb["elements"]:
lines = []
lines.append("\t\t\t\t\t{")
body = []
body.append('"origin": %s' % arr([-el["to"][0], el["from"][1], el["from"][2]]))
body.append('"size": %s' % arr([el["to"][i] - el["from"][i] for i in range(3)]))
if el.get("rotation"):
body.append('"pivot": %s' % arr([-el["origin"][0], el["origin"][1], el["origin"][2]]))
body.append('"rotation": %s' % arr([-el["rotation"][0], -el["rotation"][1], el["rotation"][2]]))
uv_lines = conv_uv(el)
txt = ",\n".join("\t\t\t\t\t\t%s" % b for b in body)
txt += ',\n\t\t\t\t\t\t"uv": {\n'
txt += ",\n".join("\t\t\t\t\t\t\t%s" % u for u in uv_lines)
txt += "\n\t\t\t\t\t\t}"
lines.append(txt)
lines.append("\t\t\t\t\t}")
cube_blocks.append("\n".join(lines))
model = []
model.append("{")
model.append('\t"format_version": "1.13.0",')
model.append('\t"netease:block_geometry": {')
model.append('\t\t"description": {')
model.append('\t\t\t"identifier": "%s",' % MODEL_ID)
model.append('\t\t\t"textures": ["%s"],' % TEX_KEY)
model.append('\t\t\t"textures_descriptions": [')
model.append('\t\t\t\t{ "width": %d, "length": %d }' % (tw, th))
model.append('\t\t\t],')
model.append('\t\t\t"use_ao": true')
model.append('\t\t},')
model.append('\t\t"bones": [')
model.append('\t\t\t{')
model.append('\t\t\t\t"name": "%s",' % BONE_NAME)
model.append('\t\t\t\t"pivot": [0, 0, 0],')
model.append('\t\t\t\t"cubes": [')
model.append(",\n".join(cube_blocks))
model.append('\t\t\t\t]')
model.append('\t\t\t}')
model.append('\t\t]')
model.append('\t}')
model.append('}')
text = "\n".join(model) + "\n"
model_dir = os.path.join(RES, "models", "netease_block")
os.makedirs(model_dir, exist_ok=True)
model_path = os.path.join(model_dir, TEX_KEY + ".json")
with open(model_path, "w", encoding="utf-8", newline="\n") as fp:
fp.write(text)
print("texture ->", tex_path)
print("model ->", model_path)
print("identifier:", MODEL_ID, "| terrain_texture key:", TEX_KEY, "| %dx%d" % (tw, th))
print("cubes:", len(bb["elements"]))
if __name__ == "__main__":
main()