Solved Directional blockdata

Discussion in 'Spigot Plugin Development' started by Janderup, Aug 29, 2018.

  1. Hello,
    I am trying to place a block through a data line which is saved like:
    X,Y,Z,Material(Ordinal),Blockface(Ordinal)

    But it doesn't work when I try to set the blockface of a block, it doesn't even place blocks like stairs, slabs etc.
    I use the following code:
    Code (Java):
    private void placeBlock(Location l, String line) {
            String[] data = line.split(",");
           
            Location blockLocation = new Location(l.getWorld(), l.getBlockX() + Integer.parseInt(data[0]),
                    l.getBlockY() + Integer.parseInt(data[1]),
                    l.getBlockZ() + Integer.parseInt(data[2]));
            Material mat = Material.values()[Integer.parseInt(data[3])];
           
            if (mat.toString().replaceAll("AIR", "-").equalsIgnoreCase(mat.toString())) {
                Block b = blockLocation.getWorld().getBlockAt(blockLocation);
               
                b.setType(mat);
                if (data.length >= 5) {
                    BlockFace bf = BlockFace.values()[Integer.parseInt(data[4])];
                   
                    Directional dir = (Directional) b.getBlockData();
                    dir.setFacing(bf);
                }
            }
        }
    This code is running in a repeating task which places 10 blocks per tick instead of building a whole structure at once to avoid lag for users in the game.
    Any help is appriciated! ;)
     
  2. Hi I use this method : (Deprecated) to put step or stairs in same position than another building :
    Code (Java):
    if (block.getType() == Material.STEP)
                                {
                                    blockDest.setData((byte) 11);
                                } else
                                    if (block.getType() == Material.COBBLESTONE_STAIRS)
                                    {
                                        blockDest.setData(block.getData());
                                    }
    For you'r code check if putting or updating block did something
     
  3. That code doesn't work on 1.13 which is the built I build my plugin on.
     
  4. and by placing or updating the block on you'r code ? It did something ?
     
  5. getSate gets a *new* copy. You need to update() the copy you've modified.
     
  6. Now I changed the code to this:

    Code (Java):
    BlockState state = b.getState();
                    Directional dir = (Directional) state.getBlockData();
                    dir.setFacing(bf);

                    state.setBlockData(dir);
                    state.update();
    But no effect, still the same as it was, it doesn't even place the block.
     
  7. set legacy to false in the plugin.yml and use Material.LEGACY_COOBLESTONE_STAIRS
    and use this method:

     
  8. But I'm building on 1.13, that code is for 1.12 and lower…
     
  9. This works fine for me:

    Code (Java):

                Block block = loc.getBlock();
                block.setType(Material.ACACIA_STAIRS);
                Directional blockData = (Directional) block.getBlockData();
                blockData.setFacing(bFace);
                block.setBlockData(blockData);
     
    I did not even had to update the blockState

    Also this:
    Block b = blockLocation.getWorld().getBlockAt(blockLocation);
    in your code is overcomplicated. Just use blockLocation#getBlock()
     
  10. No this code is for use 1.12 code in 1.13 ;)
     
    • Optimistic Optimistic x 1
  11. I added that line of Location.getBlock(). But that didn't have effect which is very understandable. But is the issue really comming from changing the block direction? Because it doesn't even place the stairs at all. Isn't it just not possible to do Block.setType(Material.OAK_STAIRS)?
     
  12. You just do not want to read, do you?

    Code (Java):
    b.setBlockData(dir);
    Where you want to add this, figure out yourself.
     
  13. Choco

    Moderator

    You are not to use this as a hack to support 1.12 and 1.13. This is for LEGACY SUPPORT ONLY!!! Plugins that have not yet updated. There are massive performance implications due to runtime bytecode manipulation and you should not ever use the legacy materials intentionally. It’s either 1.13 or 1.12 and below, make your choice.
     
  14. I already tried that or course, but that doesn't solve the issue.
     
  15. @Janderup (I'm using Spigot 1.13.1)

    First thing I want to mention is that indeed you can set block types to oak stairs. Proof:
    [​IMG]

    The second thing I noticed may be the reason why you're having this major problem. From your code snippet you shared with us you have an if statement:
    Code (Text):
    if (mat.toString().replaceAll("AIR", "-").equalsIgnoreCase(mat.toString())) {
    I debugged your method quite a bit and I noticed when comparing stairs it would actually remove the 'air' part in stair:

    [​IMG]

    So in this situation any stairs you attempted to copy would be ignored because they have air in the name. I recommend doing something similar to this if you want to ignore air blocks:
    Code (Text):
    if (!mat.equals(Material.AIR)) {
    And finally, I was able to change the direction of the stairs using this code:
    Code (Text):
    Stairs stair = ((Stairs) b.getBlockData());
    stair.setFacing(BlockFace.EAST);
    b.setBlockData(stair);
    [​IMG]

    However, at this point, things started to get tricky. I started playing around with the block data. I determined the number returned by block.getData(); for each position of the stairs.
    Code (Text):
    Facing:
      east: 0
      west: 1
      south: 2
      north: 3
     
      Upside down -
      east: 4
      west: 5
      south: 6
      north: 7
    Although there is not a BlockFace enum direction that includes the stairs that have been placed upside down. Additionally, corner stair blocks have some odd behavior. I attempted to continue the test with just right side up blocks and got this result:

    [​IMG]

    As you can see some of the corner pieces have been changed.

    I suggest perhaps attempting to pass through block data rather than a byte data to ensure the stairs are correctly oriented. Additionally I found a tool online that may help you find an accurate solution. https://github.com/PlayUniverse/Minecraft-IDTool-1.13

    **EDIT**
    I was able to find an accurate solution using the BlockData rather than the byte data.
    1. Parse the BlockData into a string:
    Code (Java):
    String stringData = block.getBlockData().getAsString()
    2. Reverse the process whenever you need the BlockData object:
    Code (Java):
    block.setBlockData(Bukkit.getServer().createBlockData(stringData));
    [​IMG]

    And with this method, wool colors and upside stairs are copied accurately:
    [​IMG]

    Here's a link to a github with my code if you want to take a look it. Apologies for the mess, but it was mainly used for testing: https://github.com/rocketrobot3/StairTest
     
    #16 Cloaking_Ocean, Sep 1, 2018
    Last edited: Sep 2, 2018
    • Agree Agree x 1
  16. Choco

    Moderator

    Just as a note, a couple things here:
    • When comparing enum constants, use == to avoid NullPointerExceptions and for the sake of best practice
    • 1.13 has multiple types of air. AIR, CAVE_AIR and VOID_AIR
     
    • Informative Informative x 1
  17. You are right, I changed that like to:
    Code (Java):
    if (mat != Material.AIR && mat != Material.CAVE_AIR) {
    and this solves the issue. I ever added the line because there were multiple types of air unknowing that it also filters the stairs.
    Thanks everyone for your help, really appriciated ;)
     
    • Like Like x 1