SchematicPlacer.java 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. package me.lethunderhawk.world.util.schematic;
  2. import com.google.gson.Gson;
  3. import com.google.gson.JsonParseException;
  4. import com.sk89q.worldedit.EditSession;
  5. import com.sk89q.worldedit.WorldEdit;
  6. import com.sk89q.worldedit.bukkit.BukkitAdapter;
  7. import com.sk89q.worldedit.extent.clipboard.Clipboard;
  8. import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
  9. import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
  10. import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
  11. import com.sk89q.worldedit.function.operation.Operation;
  12. import com.sk89q.worldedit.function.operation.Operations;
  13. import com.sk89q.worldedit.math.BlockVector3;
  14. import com.sk89q.worldedit.session.ClipboardHolder;
  15. import org.bukkit.Location;
  16. import org.bukkit.World;
  17. import java.io.File;
  18. import java.io.FileInputStream;
  19. import java.io.FileReader;
  20. import java.io.IOException;
  21. public final class SchematicPlacer {
  22. private static final Gson GSON = new Gson();
  23. private SchematicPlacer() {}
  24. /**
  25. * Places a schematic at a world location.
  26. *
  27. * @param schematicFile .schem file
  28. * @param world target world
  29. * @param anchor world-space anchor
  30. * @param rotation rotation to apply
  31. * @return true if placed successfully
  32. */
  33. public static boolean place(
  34. File schematicFile,
  35. World world,
  36. Location anchor,
  37. Rotation rotation
  38. ) {
  39. if (!isValidSchematic(schematicFile)) return false;
  40. SchematicMetadata metadata = loadMetadata(schematicFile);
  41. Clipboard clipboard = loadClipboard(schematicFile);
  42. if (clipboard == null) return false;
  43. if (metadata != null) {
  44. // BoundingBox box = metadata
  45. // .boundingBox()
  46. // .shift(anchor.toVector());
  47. // Optional validation
  48. // if (!isAreaClear(world, box)) return false;
  49. }
  50. Vector3i schematicAnchor =
  51. metadata != null ? metadata.anchor() : new Vector3i(0,0,0);
  52. return paste(
  53. clipboard,
  54. world,
  55. anchor,
  56. schematicAnchor,
  57. rotation
  58. );
  59. }
  60. // ----------------------------------------------------------------
  61. private static boolean isValidSchematic(File file) {
  62. return file != null && file.exists() && file.getName().endsWith(".schem");
  63. }
  64. private static Clipboard loadClipboard(File file) {
  65. ClipboardFormat format = ClipboardFormats.findByPath(file.toPath());
  66. if (format == null) return null;
  67. try (ClipboardReader reader =
  68. format.getReader(new FileInputStream(file))) {
  69. return reader.read();
  70. } catch (IOException e) {
  71. return null;
  72. }
  73. }
  74. private static SchematicMetadata loadMetadata(File schematic) {
  75. File meta = new File(
  76. schematic.getParent(),
  77. schematic.getName().replace(".schem", ".json")
  78. );
  79. if (!meta.exists()) return null;
  80. try (FileReader reader = new FileReader(meta)) {
  81. return GSON.fromJson(reader, SchematicMetadata.class);
  82. } catch (IOException | JsonParseException e) {
  83. return null;
  84. }
  85. }
  86. private static boolean paste(
  87. Clipboard clipboard,
  88. World world,
  89. Location anchor,
  90. Vector3i schematicAnchor,
  91. Rotation rotation
  92. ) {
  93. com.sk89q.worldedit.world.World weWorld =
  94. BukkitAdapter.adapt(world);
  95. BlockVector3 target = BlockVector3.at(
  96. anchor.getBlockX() - schematicAnchor.x(),
  97. anchor.getBlockY() - schematicAnchor.y(),
  98. anchor.getBlockZ() - schematicAnchor.z()
  99. );
  100. try (EditSession session = WorldEdit.getInstance()
  101. .newEditSessionBuilder()
  102. .world(weWorld)
  103. .build()) {
  104. ClipboardHolder holder = new ClipboardHolder(clipboard);
  105. holder.setTransform(
  106. holder.getTransform().combine(rotation.toTransform())
  107. );
  108. Operation operation = holder
  109. .createPaste(session)
  110. .to(target)
  111. .ignoreAirBlocks(true)
  112. .build();
  113. Operations.complete(operation);
  114. return true;
  115. } catch (Exception e) {
  116. return false;
  117. }
  118. }
  119. }