package me.lethunderhawk.world.util.schematic; import com.google.gson.Gson; import com.google.gson.JsonParseException; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.session.ClipboardHolder; import org.bukkit.Location; import org.bukkit.World; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; public final class SchematicPlacer { private static final Gson GSON = new Gson(); private SchematicPlacer() {} /** * Places a schematic at a world location. * * @param schematicFile .schem file * @param world target world * @param anchor world-space anchor * @param rotation rotation to apply * @return true if placed successfully */ public static boolean place( File schematicFile, World world, Location anchor, Rotation rotation ) { if (!isValidSchematic(schematicFile)) return false; SchematicMetadata metadata = loadMetadata(schematicFile); Clipboard clipboard = loadClipboard(schematicFile); if (clipboard == null) return false; if (metadata != null) { // BoundingBox box = metadata // .boundingBox() // .shift(anchor.toVector()); // Optional validation // if (!isAreaClear(world, box)) return false; } Vector3i schematicAnchor = metadata != null ? metadata.anchor() : new Vector3i(0,0,0); return paste( clipboard, world, anchor, schematicAnchor, rotation ); } // ---------------------------------------------------------------- private static boolean isValidSchematic(File file) { return file != null && file.exists() && file.getName().endsWith(".schem"); } private static Clipboard loadClipboard(File file) { ClipboardFormat format = ClipboardFormats.findByPath(file.toPath()); if (format == null) return null; try (ClipboardReader reader = format.getReader(new FileInputStream(file))) { return reader.read(); } catch (IOException e) { return null; } } private static SchematicMetadata loadMetadata(File schematic) { File meta = new File( schematic.getParent(), schematic.getName().replace(".schem", ".json") ); if (!meta.exists()) return null; try (FileReader reader = new FileReader(meta)) { return GSON.fromJson(reader, SchematicMetadata.class); } catch (IOException | JsonParseException e) { return null; } } private static boolean paste( Clipboard clipboard, World world, Location anchor, Vector3i schematicAnchor, Rotation rotation ) { com.sk89q.worldedit.world.World weWorld = BukkitAdapter.adapt(world); BlockVector3 target = BlockVector3.at( anchor.getBlockX() - schematicAnchor.x(), anchor.getBlockY() - schematicAnchor.y(), anchor.getBlockZ() - schematicAnchor.z() ); try (EditSession session = WorldEdit.getInstance() .newEditSessionBuilder() .world(weWorld) .build()) { ClipboardHolder holder = new ClipboardHolder(clipboard); holder.setTransform( holder.getTransform().combine(rotation.toTransform()) ); Operation operation = holder .createPaste(session) .to(target) .ignoreAirBlocks(true) .build(); Operations.complete(operation); return true; } catch (Exception e) { return false; } } }