Solved [1.9] Get plant's growth stage

Discussion in 'Spigot Plugin Development' started by Otisdiver, May 14, 2016.

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

    I've been having trouble figuring out how to get a plant (e.g. wheat)'s growth stage from a break event. Basically, I need to set the block to air when it's broken if it's not fully grown.

    I found this on the JavaDocs, but still, not sure how to retrieve it: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/CropState.html

    I was trying to do this:
    Code (Text):
        public boolean isFullyGrown(Block block) {
            if (block.getState().equals(CropState.RIPE)) return true;
            return false;
        }
    but it was always returning true, and then the other section of the code would set it to air regardless of growth stage.

    Here's the code that calls the boolean method: http://pastebin.com/pkMga1SL
    (NOTE: everything was working fine until I added the if statement on line 15.)

    How can I get the CropState out of the block? Is there another implementation I should be using? Am I missing a newbie error in my code?

    I'm running Spigot for 1.9.4.

    Thanks for your help!
     
    #1 Otisdiver, May 14, 2016
    Last edited: May 14, 2016
  2. Code (Text):
    Crops crop = (Crops) e.getBlock().getState();
    if(crop.getState().equals(CropState.RIPE)) {
           //do stuff
    }
    Here you go my good sir, I had to do a bit of research myself. That is how you check if a crop is ripe. You need to first check if the block itself is a crop.
     
    • Agree Agree x 1
  3. I tried this and I'm having the same issue. There are no errors. Here's the updated code:
    Code (Text):
        public boolean isFullyGrown(Block block) {
            // if the block is wheat
            if (block.getType().equals(Material.CROPS)) {
                // convert to a Crops object
                Crops crop  = (Crops) block.getState();
                // return true if it's fully grown
                return crop.getState().equals(CropState.RIPE);
            }
            return false;
        }
     
  4. Check if the BlockState is instanceof Crops. If so, then cast it, and check the state of the crop. Instead of checking if the block itself it equal to the Crops, check the BlockState.
     
  5. @MrWaffleman @GamerzKing Thanks both of you for your help. Unfortunately, the same issue is occurring.

    Method:
    Code (Text):
        public boolean isFullyGrown(Block block) {
            // if the block is any crop
            if (block.getState() instanceof Crops) {
                // cast to Crops
               return ((Crops) block.getState())
                  // true if growth stage is at ripe/full
                  .getState() == CropState.RIPE;
            }
            return false;
        }
    Method's call:
    Code (Text):
            // if it isn't fully grown
            if (!utils.isFullyGrown(e.getBlock())) {
                // don't go further (artificial drop won't be processed)
                e.getPlayer().sendMessage("§cThat plant wasn't fully grown.");
                return;
            }
    Here's a quick video of the code at work: http://take.ms/26O1z

    Must be an issue with the logic.
     
    #5 Otisdiver, May 14, 2016
    Last edited: May 14, 2016
  6. Alright, I figured it out!

    So after doing some research, I noticed that the Crops class extends MaterialData. This means that instead of checking if the BlockState is equal to Crops, we have to check if the data from the BlockState is equal to MaterialData. After doing some testing of this, I have concluded that this is correct, and below is how I did it.


    Code (Text):
        public boolean isFullyGrown(Block block) {

            BlockState state = block.getState();
            MaterialData data = state.getData();

            if(!(data instanceof Crops))
                return false;

                return (((Crops) data).getState() == CropState.RIPE);
        }
    Before I get hated on for spoon-feeding, I'll explain what I'm doing here.

    1. It gets the state of the block, and gets the data from the state.
    2. Checks if the data from the state is instanceof Crops. If not, we will return false, since if it's not a crop, how can it be fully grown anyways?
    3. We cast the data to Crops. Since we now know that the data physically can't be a crop, we can assume that it will always be a crop from this point. From here, the Crops class has a method called getState() which returns a CropState. So now that we have casted the data to Crops, we can get the CropState from there. If it is equal to RIPE, it will return true. Otherwise, it will return false, obviously.

    Hope I helped!
    - GamerzKing
     
    • Useful Useful x 2
  7. Yes, thank you @GamerzKing. I can confirm this solution works.

    Relevant JavaDocs (for future readers): https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/material/Crops.html

    My final code:
    Code (Text):
        public boolean isFullyGrown(Block block) {
             MaterialData md = block.getState().getData();

             if(md instanceof Crops) {
               return (((Crops) md).getState() == CropState.RIPE);
             }
             else return false;
        }
    Edit: marked as solved and closed.
     
    • Like Like x 3
    • Friendly Friendly x 2
    • Useful Useful x 1
Thread Status:
Not open for further replies.