Util Creating Structures that rotate depending on the Player's direction

Discussion in 'Resources' started by BlackKnight625, Jun 18, 2015.

?

So, what do you think?

  1. That helped me/will help me a lot!

    100.0%
  2. Nice work!

    0 vote(s)
    0.0%
  3. That wasn't very usefull

    0 vote(s)
    0.0%
Thread Status:
Not open for further replies.
  1. Offline

    BlackKnight625

    Hello, I'm BlackKnight625 and yesterday and today, I created some methods that will be pretty useful if you want to create a small structure when a Player right clicks a block or something. But as you know, if you use coordinates the structure will face the same direction every time. Well.... not anymore! :D
    So, here's how it works: First, we create a method that will return the direction that a Player is facing.
    Code:
    public static String getCardinalDirection(Player player) {
            double rotation = (player.getLocation().getYaw() - 90) % 360;
            if (rotation < 0) {
                rotation += 360.0;
            }
             if (0 <= rotation && rotation < 45) {
                return "W";
            } else if (45 <= rotation && rotation < 135) {
                return "N";         
            } else if (135 <= rotation && rotation < 225) {
                return "E";
            } else if (225 <= rotation && rotation < 315) {
                return "S";
            } else if (315 <= rotation && rotation < 360) {
                return "W";
            } else {
                return null;
            }
        }
    If you want to be more precise, then:
    Code:
    public static String getAproximateCardinalDirection(Player player) {
            double rotation = (player.getLocation().getYaw() - 90) % 360;
            if (rotation < 0) {
                rotation += 360.0;
            }
             if (0 <= rotation && rotation < 22.5) {
                return "W";
            } else if (22.5 <= rotation && rotation < 67.5) {
                return "NW";
            } else if (67.5 <= rotation && rotation < 112.5) {
                return "N";
            } else if (112.5 <= rotation && rotation < 157.5) {
                return "NE";
            } else if (157.5 <= rotation && rotation < 202.5) {
                return "E";
            } else if (202.5 <= rotation && rotation < 247.5) {
                return "SE";
            } else if (247.5 <= rotation && rotation < 292.5) {
                return "S";
            } else if (292.5 <= rotation && rotation < 337.5) {
                return "SW";
            } else if (337.5 <= rotation && rotation < 360.0) {
                return "W";
            } else {
                return null;
            }
        }
    (I copied part of this code from the internet, but the following code I made it myself.)

    So, now that we have the direction in which the Player is facing, we can generate our own structure with this:
    Code:
    //This method is Static because I put it in another Class
    public static Block createBlockRelative(Player p, String direction, int x, int y, int z, Material m) {
            int xx = p.getLocation().getBlockX();
            int yy = p.getLocation().getBlockY();
            int zz = p.getLocation().getBlockZ();
          
            Location loc = new Location(p.getWorld(), xx, yy, zz);
          
            if (direction.contains("E")) {
                loc.setX(xx + x);
                loc.setY(yy + y);
                loc.setZ(zz + z);
            }
            else if (direction.contains("S")) {
                loc.setX(xx - z);
                loc.setY(yy + y);
                loc.setZ(zz + x);
            }
            else if (direction.contains("W")) {
                loc.setX(xx - x);
                loc.setY(yy + y);
                loc.setZ(zz - z);
            }
            else if (direction.contains("N")) {
                loc.setX(xx + z);
                loc.setY(yy + y);
                loc.setZ(zz - x);
            }
                  
            loc.getBlock().setType(m);  
            return loc.getBlock();
        }
    With that method done, we can create a block like this:
    Code:
    //This is an example
    
    Player p = e.getPlayer();
    String d = getCardinalDirection(p);
    //Or
    String d = OtherClassName.getCardinalDirection(p);
    
    //Use it like this if you have the createBlockRelative method in another class
    OtherClassName.createBlockRelative(p, d, 2, 0, -1, Material.getMaterial(17));
    
    //Use it like this if you have it in the same class
    createBlockRelative(p, d, 2, 0, -1, Material.getMaterial(17));
    //Or
    createBlockRelative(p, d, 2, 0, -1, Material.WOOD);
    Ok, so when we call this method, the first arg is the Player that the Structure will be built relative to him; the second arg is the direction that it will be facing. The 3rd, 4th and 5th args are respectively x, y and z axis (remember: x points forward if you're looking EAST, y points up or down and Z points forward if you're looking SOUTH) and the 6th arg is the Block's Material.

    If we want to build a structure with the method I created, I suggest that you first create something like this to help you: http://imgur.com/Ecg3Yi6

    The x-axis is pointing EAST, because the coordinates X get positive when heading that direction. Same happens to the coordinate Z, it gets positive when heading SOUTH. That's why I made these arrows: http://imgur.com/lO1Vupe

    Now, if we want to create a simple Structure like this: http://imgur.com/9wS6JLr We would have to do something like this:
    Code:
    Structure_Generator.createBlockRelative(p, d, 2, 0, -1, Material.WOOD);
    Structure_Generator.createBlockRelative(p, d, 3, 0, -1, Material.WOOD);
    Structure_Generator.createBlockRelative(p, d, 3, 0, 0, Material.WOOD);
    Structure_Generator.createBlockRelative(p, d, 3, 0, 1, Material.WOOD);
    Build your Structure heading East. Then, stand in the blue wool and count the X, Y and Z coordinates relative to you standing in the blue wool and 1 by 1 (block) you'll build your Structure.

    Now, if you want that Structure to appear in front of a Player when he right clicks a stick, do the following:
    Code:
    @EventHandler
    public void whenPlayerRightClicksAStick(PlayerInteractEvent e) {
    
    if (e.getAction().equals(Action.RIGHT_CLICK_AIR)) {
       if (e.getPlayer().getItemInHand().getType().equals(Material.STICK)) {
    
    Player p = e.getPlayer();
    String d = getCardinalDirection(p);
    
    Structure_Generator.createBlockRelative(p, d, 2, 0, -1, Material.WOOD);
    Structure_Generator.createBlockRelative(p, d, 3, 0, -1, Material.WOOD);
    Structure_Generator.createBlockRelative(p, d, 3, 0, 0, Material.WOOD);
    Structure_Generator.createBlockRelative(p, d, 3, 0, 1, Material.WOOD);
    }
    }
    }
    You may copy the code.
    WARNING: This will work on any sticks, do the rest of the verification by yourselfs.


    Finally: If you stand in the blue wool and point in any direction, it will build your Structure according to the direction you are facing at. The final result: http://imgur.com/ZHabZ91


    So here it is. I'm very proud of my little piece of code and hopefully I will help a lot of people with this.

    Have a good day :)

    Don't mind me, just having some fun
    http://imgur.com/OmP2pJN
    http://imgur.com/JOtKkMf

    And once you get used to this, you can create pretty cool stuff!
    http://imgur.com/Fz8F3EF

    EDIT by Timtower: Don't mind me, just merging some posts
     
    Last edited: Jun 21, 2015
  2. Offline

    Totom3

    I have a few suggestions:
    • Instead of returning and parsing strings, you could use Bukkit's BlockFace enum type. Not only it would be simpler, but also it would be easier to get the relative block, since Block has a "getRelative" method which takes as a parameter a BlockFace.
    • To get the direction the player is facing, you could use a RangeMap instead of passing the yaw through multiple if checks.
    • Currently, createBlockRelative() does not support the more precise directions, such as NE and SW. Any reasons why not?
    • The Y coordinate of the block could be "computed" when creating the location.
     
  3. Offline

    BlackKnight625

    1- I prefer using the String, as I will be able to use it for further development.
    2- Well, I didn't do that part of the code, I just twicked it a bit.
    3- If it did, then the structures that would come out if you pointed any of those directions, they would form in a very weird position. EDIT: for example, if you pointed NE, the wooden L wouldn't be an L anymore... but if you want you can make another method and call it createPreciseBlockRelative(p, d, x, y, z, m), but then you would have to do the maths by yourself.
    4- What if you want to build a structure above you? You can compute it anyways and the replace the y arg for the y you want.
     
  4. Offline

    Totom3

    I can understand #1 but I still don't get the reason not to use a RangeMap (#2).

    #3 is a good reason but in this case you shouldn't bother showing how to make a more precise direction (in getAproximateCardinalDirection()).

    What I meant with #4 is that no matter what is the direction the player is facing, you are going to end up with this instruction:
    Code:
    loc.setY(yy + y);
    You could just do the addition when creating the location:
    Code:
    Location loc =new Location(p.getWorld(), xx, yy + y, zz);
     
  5. Offline

    BlackKnight625

    Ohh well... that's true. If you want, you can edit that if you copy my code.

    Well, I made that method in case I'll need it in another situation.

    I'm going to be honest: I'm a Java Programming Beginner, I have never heard of RangeMaps before...
     
  6. Offline

    xTrollxDudex

  7. Offline

    BlackKnight625

Thread Status:
Not open for further replies.

Share This Page