-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path3dconverter.py
139 lines (123 loc) · 5.07 KB
/
3dconverter.py
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
# -*- coding:utf-8 -*-
from TrimMCStruct import Structure
import os
# 本项目中受CC BY-SA 4.0协议保护的部分由此开始
def group_blocks(sorted_tiles, size):
shapes = []
tiles = sorted_tiles.copy()
while tiles:
# 获取第一个方块
model_entry = tiles.pop(0)
startX, startY, startZ = model_entry["x"], model_entry["y"], model_entry["z"]
maxX, maxY, maxZ = startX, startY, startZ
blockname = model_entry["blockname"]
# Z轴方向
z = startZ + 1
while z < size[2]:
if any(tile["x"] == startX and tile["y"] == startY and tile["z"] == z and tile["blockname"] == blockname for tile in tiles):
maxZ = z
z += 1
else:
break
# Y轴方向
y = startY + 1
while y < size[1]:
valid = True
for zi in range(startZ, maxZ+1):
if not any(tile["x"] == startX and tile["y"] == y and tile["z"] == zi and tile["blockname"] == blockname for tile in tiles):
valid = False
break
if valid:
maxY = y
y += 1
else:
break
# X轴方向
x = startX + 1
while x < size[0]:
valid = True
for yi in range(startY, maxY+1):
for zi in range(startZ, maxZ+1):
if not any(tile["x"] == x and tile["y"] == yi and tile["z"] == zi and tile["blockname"] == blockname for tile in tiles):
valid = False
break
if not valid:
break
if valid:
maxX = x
x += 1
else:
break
# 从tiles中移除已经处理的方块
to_remove = []
for i, tile in enumerate(tiles):
if (
startX <= tile["x"] <= maxX and
startY <= tile["y"] <= maxY and
startZ <= tile["z"] <= maxZ and
tile["blockname"] == blockname
):
to_remove.append(i)
for index in sorted(to_remove, reverse=True):
tiles.pop(index)
shapes.append({"blockname": blockname, "low": [startX, startY, startZ], "high": [maxX, maxY, maxZ]})
return shapes
# 本项目中受CC BY-SA 4.0协议保护的部分由此结束
def convert(path, output_path=""):
filename = os.path.splitext(os.path.basename(path))[0]
if not output_path:
output_path = f"{filename}_output.mcfunction"
with open(path, "rb") as f:
struct = Structure.load(f)
xsize, ysize, zsize = struct.size
if os.path.exists(output_path):
os.remove(output_path)
cmds = []
sorted_tiles = []
# 收集所有非空气方块
for x in range(xsize):
for y in range(ysize):
for z in range(zsize):
block = struct.get_block((x, y, z))
if block.identifier == "minecraft:air":
continue
blockname = block.stringify(
with_namespace=False,
with_states=True
).replace(": ", "=").replace(" []", "") \
.replace("=1", "=true").replace("=0", "=false") \
.replace('direction"=true', 'direction"=1') \
.replace('direction"=false', 'direction"=0') \
.replace('redstone_signal"=false', 'redstone_signal"=0') \
.replace('redstone_signal"=true', 'redstone_signal"=1') \
.replace('block_light_level"=true', 'block_light_level"=1') \
.replace('block_light_level"=false', 'block_light_level"=0') \
.replace('liquid_depth"=true', 'liquid_depth"=1') \
.replace('liquid_depth"=false', 'liquid_depth"=0') \
# 替换数据值
sorted_tiles.append({"x": x, "y": y, "z": z, "blockname": blockname})
# 使用group_blocks进行三维优化
shapes = group_blocks(sorted_tiles, [xsize, ysize, zsize])
# 生成指令
for shape in shapes:
blockname = shape["blockname"]
low = shape["low"]
high = shape["high"]
if low == high:
x, y, z = low
cmds.append(f"setblock ~{x} ~{y} ~{z} {blockname}")
else:
x1, y1, z1 = low
x2, y2, z2 = high
cmds.append(f"fill ~{x1} ~{y1} ~{z1} ~{x2} ~{y2} ~{z2} {blockname}")
print("Conversion complete.")
return "\n".join(cmds)
if __name__ == "__main__":
path = input("Please enter the path of the .mcstructure file: ")
default_output = f"{os.path.splitext(os.path.basename(path))[0]}_output.mcfunction"
output_path = input(f"Please enter the path of the output file, or press Enter to use the default path ({default_output}): ") or default_output
print("Converting, please wait...")
cmds = convert(path, output_path)
with open(output_path, "w") as f:
f.write(cmds)
print(f"File has been written to {output_path}")