Logic to generate structures?

Discussion in 'Plugin Development' started by JoshArgent, May 9, 2013.

Thread Status:
Not open for further replies.
  1. Offline

    JoshArgent

    Hi,

    I'm making a plugin for my server that basically pastes schematic files all over newly generated chunks. It all works fine except most of the time they don't fit in very well. They kind of have clean, straight edges cutting out of the land which makes them look really quite odd.

    [​IMG]

    I've tried various tactics to try and paste them cleanly but I really can't work it out. I need a similar kind of logic to how desert temples and villages are placed.

    This is what I have as of now:
    Code:
        public void ChunkLoad(ChunkLoadEvent event, Functions.Server server)
        {
            if(event.isNewChunk() && server == Functions.Server.HungerGames && event.getChunk().getWorld().getName().equalsIgnoreCase("world"))
            {
                int num = f.GetRandomNumberFrom(0, 1);
                if(num == 0)
                {
                Chunk c = event.getChunk();
                Block b = c.getWorld().getHighestBlockAt(c.getBlock(0, 0, 0).getX(), c.getBlock(0, 0, 0).getZ());
                if(c.getWorld().getBlockAt(b.getX(), b.getY() - 1, b.getZ()).isLiquid())
                {
                    return;
                }
                Location l = b.getLocation();
             
             
                num = f.GetRandomNumberFrom(1, 4);
                if(num == 2)
                {
                    l = new Location(b.getWorld(), b.getX(), b.getY() - 1, b.getZ());
                }
                if(num == 1)
                {
                    l = new Location(b.getWorld(), b.getX(), b.getY() - 4, b.getZ());
                }
                if(num == 4)
                {
                    l = new Location(b.getWorld(), b.getX(), b.getY() - 5, b.getZ());
                }
             
                if(ruins.isEmpty())
                {
                    loadSchematics();
                }
                Schematic s = ruins.get(num - 1);
             
             
             
             
                int xadd = (int) (l.getX() + s.getWidth());
                int yadd = (int) (l.getY() + s.getLenght());
                Location corner1 = l.getWorld().getHighestBlockAt(xadd, yadd).getLocation();
             
                int x2 = (int) l.getX();
                int y2 = (int) (l.getY() + s.getLenght());
                Location corner2 = l.getWorld().getHighestBlockAt(x2, y2).getLocation();
             
                int x3 = (int) l.getX() + s.getWidth();
                int y3 = (int) l.getY();
                Location corner3 = l.getWorld().getHighestBlockAt(x3, y3).getLocation();
             
                int p1 = (int) (corner1.getY() - l.getY());
                int p2 = (int) (corner2.getY() - l.getY());
                int p3 = (int) (corner3.getY() - l.getY());
             
             
                if(p1 >= -1 && p1 <= 1 && p2 >= -1 && p2 <= 1 && p3 >= -1 && p3 <= 1)
                {         
                    pasteSchematic(c.getWorld(), l, s);
                }
             
             
                }
            }
        }
    Thanks,
    Josh.
     
  2. Offline

    caseif

    I would suggest looking at WorldEdit's code, specifically the smoothing function. Then you might be able to get your foot in the door.
     
    JoshArgent likes this.
  3. Offline

    JoshArgent

    Thanks for the advice, I'll make sure to take a look. :)
     
  4. Offline

    JoshArgent

  5. Offline

    devilquak

    JoshArgent

    If you create your schematic with only exactly what you want pasted, you can paste just those blocks through WorldEdit. It pastes every block except air if you want it to, so that it "molds" to the terrain around it.
     
  6. Offline

    JoshArgent

    How do I make it paste a schematic and ignore the air? This is the code I use to paste schematics:
    Code:
    public Schematic loadSchematicFile(String file)
    {
    Schematic s = null;
    try {
    s = loadSchematic(new File(file));
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    return s;
    }
     
    public void pasteSchematic(World world, Location loc, Schematic schematic)
       {
           byte[] blocks = schematic.getBlocks();
           byte[] blockData = schematic.getData();
     
           short length = schematic.getLenght();
           short width = schematic.getWidth();
           short height = schematic.getHeight();
     
           for (int x = 0; x < width; ++x) {
               for (int y = 0; y < height; ++y) {
                   for (int z = 0; z < length; ++z) {
                       int index = y * width * length + z * width + x;
                       Block block = new Location(world, x + loc.getX(), y + loc.getY(), z + loc.getZ()).getBlock();
                       block.setTypeIdAndData(blocks[index], blockData[index], true);
                   }
               }
           }
       }
     
       public Schematic loadSchematic(File file) throws IOException
       {
           FileInputStream stream = new FileInputStream(file);
           NBTInputStream nbtStream = new NBTInputStream(new GZIPInputStream(stream));
     
           CompoundTag schematicTag = (CompoundTag) nbtStream.readTag();
           if (!schematicTag.getName().equals("Schematic")) {
               throw new IllegalArgumentException("Tag \"Schematic\" does not exist or is not first");
           }
     
           Map<String, Tag> schematic = schematicTag.getValue();
           if (!schematic.containsKey("Blocks")) {
               throw new IllegalArgumentException("Schematic file is missing a \"Blocks\" tag");
           }
     
           short width = getChildTag(schematic, "Width", ShortTag.class).getValue();
           short length = getChildTag(schematic, "Length", ShortTag.class).getValue();
           short height = getChildTag(schematic, "Height", ShortTag.class).getValue();
     
           String materials = getChildTag(schematic, "Materials", StringTag.class).getValue();
           if (!materials.equals("Alpha")) {
               throw new IllegalArgumentException("Schematic file is not an Alpha schematic");
           }
     
           byte[] blocks = getChildTag(schematic, "Blocks", ByteArrayTag.class).getValue();
           byte[] blockData = getChildTag(schematic, "Data", ByteArrayTag.class).getValue();
           return new Schematic(blocks, blockData, width, length, height);
       }
     
       private static <T extends Tag> T getChildTag(Map<String, Tag> items, String key, Class<T> expected) throws IllegalArgumentException
       {
           if (!items.containsKey(key)) {
               throw new IllegalArgumentException("Schematic file is missing a \"" + key + "\" tag");
           }
           Tag tag = items.get(key);
           if (!expected.isInstance(tag)) {
               throw new IllegalArgumentException(key + " tag is not of tag type " + expected.getName());
           }
           return expected.cast(tag);
       }
    
    Thanks for your help. :)
     
  7. Offline

    devilquak

    JoshArgent

    If you're willing to use WorldEdit, you can just use WorldEdit's paste method, and make the boolean value "ignoreAir" true. If you do use WorldEdit, you might as well use WorldEdit's loading method as well.

    However, if you don't want to do that, just try to add a check in your methods to see if a block to be pasted in a schematic is air or not.
     
  8. Offline

    JoshArgent

    Thanks, the last suggestions would probably be easier for me. The only issue now is that if the schematic is placed on the side of a hill it will rise out the ground. (Like in the image) Whats the best solution for that?

    Bump

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 1, 2016
  9. Offline

    bennie3211

    Why do you not paste only the building, without any blocks beneath it?
     
Thread Status:
Not open for further replies.

Share This Page