SchematicRoomPlacer.java 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. package me.lethunderhawk.dungeon.placement;
  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.extent.clipboard.Clipboard;
  7. import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
  8. import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
  9. import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
  10. import com.sk89q.worldedit.function.operation.Operation;
  11. import com.sk89q.worldedit.function.operation.Operations;
  12. import com.sk89q.worldedit.math.BlockVector3;
  13. import com.sk89q.worldedit.session.ClipboardHolder;
  14. import com.sk89q.worldedit.bukkit.BukkitAdapter;
  15. import me.lethunderhawk.world.util.schematic.Rotation;
  16. import me.lethunderhawk.world.util.schematic.Vector3i;
  17. import org.bukkit.Location;
  18. import org.bukkit.World;
  19. import org.bukkit.util.BoundingBox;
  20. import java.io.File;
  21. import java.io.FileReader;
  22. import java.io.IOException;
  23. public final class SchematicRoomPlacer {
  24. private static final Gson GSON = new Gson();
  25. private SchematicRoomPlacer() {}
  26. /**
  27. * Places a room schematic at a given anchor.
  28. *
  29. * @param schematicFile .schem file
  30. * @param world Bukkit world
  31. * @param anchor anchor location (world-space origin)
  32. * @param rotation rotation (NONE, CLOCKWISE_90, CLOCKWISE_180, CLOCKWISE_270)
  33. * @return true if successfully validated and placed
  34. */
  35. public static boolean placeRoom(
  36. File schematicFile,
  37. World world,
  38. Location anchor,
  39. Rotation rotation
  40. ) {
  41. if(schematicFile == null) return false;
  42. if (!schematicFile.exists()) return false;
  43. RoomMetadata meta = loadMetadata(schematicFile);
  44. if (meta == null) return false;
  45. Clipboard clipboard = loadClipboard(schematicFile);
  46. if (clipboard == null) return false;
  47. BoundingBox box = meta.boundingBox.rotated(rotation).shift(anchor.toVector());
  48. //if (!isAreaClear(world, box)) return false;
  49. return pasteClipboard(clipboard, world, anchor, meta.anchor, rotation);
  50. }
  51. // ---------- Internal ----------
  52. private static Clipboard loadClipboard(File file) {
  53. ClipboardFormat format = ClipboardFormats.findByPath(file.getAbsoluteFile().toPath());
  54. if (format == null) return null;
  55. try (ClipboardReader reader = format.getReader(new java.io.FileInputStream(file))) {
  56. return reader.read();
  57. } catch (IOException e) {
  58. return null;
  59. }
  60. }
  61. private static RoomMetadata loadMetadata(File schematic) {
  62. File metaFile = new File(schematic.getParent(), schematic.getName().replace(".schem", ".json"));
  63. if (!metaFile.exists()) return null;
  64. try (FileReader reader = new FileReader(metaFile)) {
  65. return GSON.fromJson(reader, RoomMetadata.class);
  66. } catch (IOException | JsonParseException e) {
  67. return null;
  68. }
  69. }
  70. private static boolean isAreaClear(World world, BoundingBox box) {
  71. int minX = (int) box.getMinX();
  72. int minY = (int) box.getMinY();
  73. int minZ = (int) box.getMinZ();
  74. int maxX = (int) box.getMaxX();
  75. int maxY = (int) box.getMaxY();
  76. int maxZ = (int) box.getMaxZ();
  77. for (int x = minX; x <= maxX; x++) {
  78. for (int y = minY; y <= maxY; y++) {
  79. for (int z = minZ; z <= maxZ; z++) {
  80. if (!world.getBlockAt(x, y, z).isEmpty()) {
  81. return false;
  82. }
  83. }
  84. }
  85. }
  86. return true;
  87. }
  88. private static boolean pasteClipboard(
  89. Clipboard clipboard,
  90. World world,
  91. Location anchor,
  92. Vector3i schematicAnchor,
  93. Rotation rotation
  94. ) {
  95. com.sk89q.worldedit.world.World weWorld = BukkitAdapter.adapt(world);
  96. BlockVector3 pastePos = BlockVector3.at(
  97. anchor.getBlockX() - schematicAnchor.x(),
  98. anchor.getBlockY() - schematicAnchor.y(),
  99. anchor.getBlockZ() - schematicAnchor.z()
  100. );
  101. try (EditSession session = WorldEdit.getInstance()
  102. .newEditSessionBuilder()
  103. .world(weWorld)
  104. .build()) {
  105. ClipboardHolder holder = new ClipboardHolder(clipboard);
  106. holder.setTransform(holder.getTransform().combine(rotation.toTransform()));
  107. Operation op = holder
  108. .createPaste(session)
  109. .to(pastePos)
  110. .ignoreAirBlocks(true)
  111. .build();
  112. Operations.complete(op);
  113. session.close();
  114. return true;
  115. } catch (Exception e) {
  116. return false;
  117. }
  118. }
  119. }