Open MSpaceDev opened 1 year ago
This is a problem stemming from rotating a structure with a mixture of even and odd lengths. If all sides are even the centre point is on the corner of the blocks and if both sides are odd it is in the centre of a block. If one is odd and one is even the rotation point is on the face between two of the blocks. When rotating this state the blocks don't align with the grid and it gets complicated. My solution to this problem was to round the rotation point down to the most negative corner of the centre block. Doing so has introduced this problem.
This code should solve your problem.
import glob
import os
from math import floor
import amulet
from amulet.level.formats.mcstructure import MCStructureFormatWrapper
from amulet.api.selection import SelectionGroup
from amulet.api.selection import SelectionBox
def process_schematics(schematic_dir: str, output_dir: str):
for schematic_path in glob.glob(os.path.join(glob.escape(schematic_dir), "**/*.schem"), recursive=True):
schematic = amulet.load_level(schematic_path)
# Get bounds of schematic
bounds = schematic.bounds("main")
x_size = bounds.max_x - bounds.min_x
y_size = bounds.max_y - bounds.min_y
z_size = bounds.max_z - bounds.min_z
# Get basename of structure
basename = os.path.basename(schematic_path)[:-len(".schem")].replace(" ", "_")
x_mid = x_size // 2
y_mid = y_size // 2
z_mid = z_size // 2
for rotation, shape, paste_pos in (
(0, (x_size, y_size, z_size), (x_mid, y_mid, z_mid)),
(90, (z_size, y_size, x_size), (z_mid, floor(y_mid), x_size - x_mid)),
(180, (x_size, y_size, z_size), (x_size - x_mid, floor(y_mid), z_size - z_mid)),
(270, (z_size, y_size, x_size), (z_size - z_mid, y_mid, x_mid)),
):
mcstructure_path = os.path.join(output_dir, f"{basename}_{rotation}.mcstructure")
mcstructure_wrapper = MCStructureFormatWrapper(mcstructure_path)
# Create new mcstructure file with correct bounds
mcstructure_wrapper.create_and_open(
"bedrock", (1, 20, 0),
SelectionGroup(SelectionBox((0, 0, 0), shape)),
True
)
mcstructure_wrapper.save()
mcstructure_wrapper.close()
# Paste the schematic in the mcstructure
mcstructure_level = amulet.load_level(mcstructure_path)
mcstructure_level.paste(schematic, "main", bounds, "main", paste_pos, (1.0, 1.0, 1.0), (0.0, rotation, 0.0))
mcstructure_level.save()
mcstructure_level.close()
def main():
# Place schematics & create mcstructures
process_schematics("schematics", "out")
if __name__ == '__main__':
main()
Describe the bug I have a script that takes in .schem files from Java, and converts them to Bedrock .mcstructure.
I have managed to get the code working for rotations [0, 90, 270], however 180 is not working. There is an air gap on the X-most edge, where my structure is cut off. It pastes air, meaning the blank structure size is correct. The Z-edge is fine. What could be causing the X-edge to be air?
To Reproduce Steps to reproduce the behavior:
import amulet from amulet.api.level import World from amulet.api.level import Structure from amulet.level.formats.mcstructure import MCStructureFormatWrapper from amulet.level.formats.schematic import SchematicFormatWrapper from amulet.api.selection import SelectionGroup from amulet.api.selection import SelectionBox
def load_schematics(schematic_files: List[str]) -> List[Structure]: schematics = [] for schematic_file in schematic_files: with open(schematic_file, "rb") as f: schematics.append(amulet.load_level(schematic_file)) return schematics
def process_schematics(schematic_files: List[str], schematics: List[Structure]): for i, schematic in enumerate(schematics):
Get bounds of schematic
def main():
Load all schematics