Util Schematic saving, loading, and pasting

Discussion in 'Resources' started by AndrewAnderVille, Jan 17, 2015.

Thread Status:
Not open for further replies.
  1. Hello guys. I have a small class that I created to save, load, and paste Minecraft schematics in game. As of right now it only supports block types, but if you want you can post an adaptation or later on I will add it in.

    Code:java
    1.  
    2. import java.io.File;
    3. import java.io.FileInputStream;
    4. import java.io.FileOutputStream;
    5. import java.io.IOException;
    6. import java.i:confused:bjectInputStream;
    7. import java.i:confused:bjectOutputStream;
    8. import java.util.Arrays;
    9.  
    10. import org.bukkit.Location;
    11. import org.bukkit.block.Block;
    12. import org.bukkit.plugin.Plugin;
    13.  
    14. public class StructureAPI {
    15.  
    16. Plugin plugin;
    17.  
    18. public StructureAPI(Plugin pl){
    19. this.plugin = pl;
    20. }
    21.  
    22. /**
    23.   * Get all blocks between two points and return a 3d array
    24.   */
    25.  
    26. public int[][][] getStructure(Block block, Block block2){
    27. int minX, minZ, minY;
    28. int maxX, maxZ, maxY;
    29.  
    30.  
    31. //Couldv'e used Math.min()/Math.max(), but that didn't occur to me until after I finished this :D
    32. minX = block.getX() < block2.getX() ? block.getX() : block2.getX();
    33. minZ = block.getZ() < block2.getZ() ? block.getZ() : block2.getZ();
    34. minY = block.getY() < block2.getY() ? block.getY() : block2.getY();
    35.  
    36. maxX = block.getX() > block2.getX() ? block.getX() : block2.getX();
    37. maxZ = block.getZ() > block2.getZ() ? block.getZ() : block2.getZ();
    38. maxY = block.getY() > block2.getY() ? block.getY() : block2.getY();
    39.  
    40. int[][][] blocks = new int[maxX-minX+1][maxY-minY+1][maxZ-minZ+1];
    41.  
    42. for(int x = minX; x <= maxX; x++){
    43.  
    44. for(int y = minY; y <= maxY; y++){
    45.  
    46. for(int z = minZ; z <= maxZ; z++){
    47.  
    48. Block b = block.getWorld().getBlockAt(x, y, z);
    49. blocks[x-minX][y-minY][z-minZ] = b.getTypeId();
    50. }
    51. }
    52. }
    53.  
    54. return blocks;
    55.  
    56. }
    57.  
    58.  
    59. /**
    60.   * Pastes a structure to a desired location
    61.   */
    62.  
    63. public void paste(int[][][] blocks, Location l){
    64. for(int x = 0; x < blocks.length; x++){
    65.  
    66. for(int y = 0; y < blocks[x].length; y++){
    67.  
    68. for(int z = 0; z < blocks[x][y].length; z++){
    69. Location neww = l.clone();
    70. neww.add(x, y, z);
    71. Block b = neww.getBlock();
    72. if(blocks[x][y][z] != 0){
    73. b.setTypeId(blocks[x][y][z]);
    74. b.getState().update(true);
    75. }
    76. }
    77.  
    78. }
    79. }
    80. }
    81.  
    82. /**
    83.   * Save a structure with a desired name
    84.   */
    85.  
    86. public void save(String name, int[][][] b){
    87. ObjectOutputStream oos = null;
    88. FileOutputStream fout = null;
    89.  
    90. File f = new File(plugin.getDataFolder() + "/schematics/"+ name + ".schem");
    91. File dir = new File(plugin.getDataFolder() + "/schematics");
    92.  
    93. try {
    94. dir.mkdirs();
    95. f.createNewFile();
    96. } catch (IOException e1) {
    97. e1.printStackTrace();
    98. }
    99.  
    100. try{
    101. fout = new FileOutputStream(f);
    102. oos = new ObjectOutputStream(fout);
    103. oos.writeObject(b);
    104. } catch (Exception e) {
    105. e.printStackTrace();
    106. }finally {
    107. if(oos != null){
    108. try {
    109. oos.close();
    110. } catch (IOException e) {
    111. e.printStackTrace();
    112. }
    113. }
    114. }
    115. }
    116.  
    117. /**
    118.   * Load structure from file
    119.   */
    120.  
    121. public int[][][] load(String name){
    122.  
    123. File f = new File(plugin.getDataFolder() + "/schematics/"+ name + ".schem");
    124.  
    125. int[][][] loaded = new int[0][0][0];
    126.  
    127. try {
    128. FileInputStream streamIn = new FileInputStream(f);
    129. ObjectInputStream objectinputstream = new ObjectInputStream(streamIn);
    130. loaded = (int[][][])objectinputstream.readObject();
    131.  
    132. objectinputstream.close();
    133.  
    134. } catch (Exception e) {
    135.  
    136. e.printStackTrace();
    137. }
    138.  
    139. return loaded;
    140. }
    141.  
    142. /**
    143.   * Some methods I used to test
    144.   *
    145.   */
    146.  
    147. public void printArray(int[][][] a){
    148. for(int i = 0; i < a.length; i++){
    149. System.out.println(toString(a[I]));
    150. }
    151. }
    152.  
    153. public String toString(int[][] a){
    154. String s = "";
    155. for (int row=0; row < a.length ; ++row) {
    156. s += Arrays.toString(a[row]) + "\n";
    157. }
    158. return s;
    159. }
    160.  
    161.  
    162.  
    163. }[/I]
     
    Last edited: Jan 17, 2015
    StefanXX and GrandmaJam like this.
  2. Offline

    Skyost

  3. Offline

    Skyost

    @AndrewAnderVille No.
    EDIT : Well, you still need jnbt, but I think it is more stable.
     
    Last edited: Jan 18, 2015
  4. Offline

    Shawckz

    Nice
     
    AndrewAnderVille likes this.
  5. Offline

    xTrollxDudex

    ObjectInputStream? You're serious right?
     
  6. What do you mean? Is there something wrong with using that ? Could you suggest an alternative?
     
  7. Offline

    xTrollxDudex

    You must not know how slow Java's serialisation is.
     
  8. Yeah, but I figured that loading and saving is mostly a one time thing. After that the objects can be held in memory so it shouldn't affect that much.
     
  9. Offline

    Tommy Raids

    Edit: Forgot how 2 read :p

    @AndrewAnderVille Can you give me an explanation on the paste method? It's somewhat confusing to me.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 13, 2016
  10. Code:java
    1.  
    2. public void paste(int[][][] blocks, Location l){
    3. //loop through x values
    4. for(int x = 0; x < blocks.length; x++){
    5. //loop through y values for the current x value
    6. for(int y = 0; y < blocks[x].length; y++){
    7. //loop through all z values for the current x and y value
    8. for(int z = 0; z < blocks[x][y].length; z++){
    9. Location neww = l.clone();
    10. //goes to new location in relation to start
    11. neww.add(x, y, z);
    12. Block b = neww.getBlock();
    13. //checks if the block is not air
    14. if(blocks[x][y][z] != 0){
    15. //if it isn't it will replace it with the id at the x y z coordinate
    16. b.setTypeId(blocks[x][y][z]);
    17. b.getState().update(true);
    18. }
    19. }
    20.  
    21. }
    22. }
    23. }

    I hope this helps a little if you have another question could you elaborate on the specifics you're having issues with ?
     
  11. Offline

    Tommy Raids

    @AndrewAnderVille
    I'll read over it some more, but can I paste the schematic without any block type specifics? I don't see a need for that.. Say I had created a castle or anything, and in my plugin I wanted to load and paste it at a command, what would i put for x, y, z? Thanks
     
    Last edited: Jan 18, 2015
  12. You either use getStructure or load to get the int[][][] object. Basically the array stores the block ids. The location of the block id in the array is the location it will be when it is pasted.
     
  13. Offline

    Tommy Raids

    @AndrewAnderVille I apperciate you trying to explain but you're lib is really too hard to read. I'm not a noob, and I've coded a lot of things, but this just seems a little weird. Could you point me in the right direction? Here's my code so far.
    Code:
    StructureAPI.load("end");
                StructureAPI.paste(/* what goes here ;-; */, p.getLocation());
    Your API is very confusing to me, please help and point me in the right direction. My code is in the other post ;-;

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 13, 2016
  14. The load method returns what you put in "/* what goes here ;-; */". So you should have something like this.
    Code:
                StructureAPI.paste(StructureAPI.load("end"), p.getLocation());
    or load the 3d array before hand, store it and do something like
    Code:
                StructureAPI.paste(end, p.getLocation());
    Where 'end' is an int[][][]
     
    Tommy Raids likes this.
  15. Offline

    Tommy Raids

    Thank you man :p Sorry for not understanding xD

    @AndrewAnderVille
    Alright, I got the paste thing to work. But, the plugin can't seem to get the file? I created a file in the server folder called "schematics" and put a .schematic file from WorldEdit into it, assuming .schem and .schematic are the same.. Anyadvice?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 13, 2016
    AndrewAnderVille likes this.
  16. This is just a simple schematic system. It's different than world edit format. I used this for a private project, however this util http://bukkit.org/threads/pasting-loading-schematics.87129/ can load and paste world edit format, but it does not save from the world.
     
  17. Offline

    Tommy Raids

    @AndrewAnderVille
    Yeah, i've looked at that util. It's just I was confused with the lib I downloaded, there wasn't a jar. :p
    Anyways, is there anyway I can create schems that will work with this util, or do you has a tutorial on how to get the lib with the plugin for that one? :p

    EDIT: If you use McEdit for the schem, I'll use that. xD
     
    Last edited: Jan 19, 2015
  18. Offline

    gogobebe2

    This is really helpful, thanks xxx
     
Thread Status:
Not open for further replies.

Share This Page