Generalized API for crops

Discussion in 'Spigot Plugin Development' started by Crypnotic, Sep 9, 2018.

  1. So I've recently started working on a plugin regarding farming, but I have found it to be a pain to determine if a block is a type of crop or not. Is there a method built into the API that characterizes a block as a crop?

    EDIT: Since it is apparently really difficult to understand this concept. I'm going to try to make it a little more apparent.

    I am trying to figure out what Material a crop uses as a seed and what it produces.

    So, wheat would produce wheat and the seeds would be seeds.
    Carrots, produce carrots, seed carrots

    I'm trying to do this without writing a utility class to define them myself. Such as:

    Why don't I do this myself? I don't have the time to make sure it is on par with what the Spigot code base needs
    #1 Crypnotic, Sep 9, 2018
    Last edited: Sep 10, 2018
  2. MrGeneralQ

    MrGeneralQ Previously qintinator

    ItemStack crop = new ItemStack(Material.CROPS);
    if(crop.getData() == 7)
    // do your stuff

    It could be that the number is different
  3. So from that, how can you determine the product and seeds that crop drops without expressly defining them?
  4. MrGeneralQ

    MrGeneralQ Previously qintinator

    Could you please specify what the exact target would be?
  5. So say on BlockGrowEvent when a piece of wheat grows, all it provides is the new BlockState. How would I use a BlockState and get the seeds and wheat that it would produce without expressly checking for wheat
  6. MrGeneralQ

    MrGeneralQ Previously qintinator

    I'm not entirely sure. But what you could do is predefine this in your plugin in a HashMap. Other then that, I don't see a clean way. If anyone else has a better solution, please tell
  7. Currently I have to do something like this, which breaks with the 1.12-1.13 update.
    Code (Text):

    public static enum CropSpec {

        CARROT(Material.CARROTS, Material.CARROT, Material.CARROT),


        POTATO(Material.POTATOES, Material.POTATO, Material.POTATO),

        WHEAT(Material.WHEAT, Material.WHEAT, Material.WHEAT_SEEDS);

        private final Material block;
        private final Material product;
        private final Material seed;

        public static boolean isCrop(Material material) {
            for (CropSpec type : values()) {
                if (type.getBlock() == material) {
                    return true;
            return false;

        public static CropSpec getCropSpec(Material material) {
            for (CropSpec type : values()) {
                if (type.getBlock() == material) {
                    return type;
            return null;
  8. MrGeneralQ

    MrGeneralQ Previously qintinator

    Update: I'm not sure if I'll be able to help you out. I need more and clear information in order to help you out. Most likely it's just me not understanding it, I hope you find a solution and I hope that I'll be the one able to help you out
  9. Choco


    If you're working with Materials, you either use the 1.13 API or you don't. There's no in-between. Build two separate versions, one for 1.12 and below, another for 1.13
  10. My goal isn't to make build that supports both versions. My goal is to find a better way to determine if a Block is a crop and then get the drops from it
  11. joehot200


    Take a look at XMaterial.

    It's honestly so good that I'm actually using it in AntiAura's upcoming 1.13 update (with the author's permission, of course).

    Basically, XMaterial allows you to check if a block is a certain material, no matter if it's a 1.13 or 1.12 material (it does a bunch of other stuff too but it looks like that's what you're looking for).
    • Agree Agree x 1
  12. Block#getDrops then get one of the items and get the material and check if it is edible Material#isEdible shouldn't break in 1.13

    Edit: I guess this wouldn't work with every crop, like wheat nvm
  13. I'm trying to avoid anything predefined outside of Bukkit/Spigot. My best case scenario would be something like.
    Code (Text):
    BlockState state = event.getNewState();
    Block block = state.getBlock();
    if (state.isCrop()) { // Maybe even #isGrowable
        CropData crop = (CropData) state.getData();
        if (crop.getState() == CropState.RIPE) {
            block.getWorld().dropItem(block.getLocation(), new ItemStack(crop.getProduct(), 1));
            block.getWorld().dropItem(block.getLocation(), new ItemStack(crop.getSeed(), random.nextInt(3) + 1));

    If you'll notice, the code above never references any specific crop. Just a generic data type

    If anyone has the time and know-how to PR this for API, I would be very thankful. I just don't have the time
    #14 Crypnotic, Sep 10, 2018
    Last edited: Sep 10, 2018
  14. getBlock returns the block that grew from.

    To get the block that was produced, use getNewState().getBlock()
  15. I know. That was not the point of the post. I typed that out in the reply box. Maybe stick to trying to help with the real issue at hand
  16. You are asking us to make you an API when you don't need one. You know what the block is, right? Well you now check the block material and compare it to an arraylist that stores all materials of crops. If the arraylist contains the material it is a crop. Get the drops via getBlock#getDrops.

    Code (Text):

        List<Material> cropMaterials = new ArrayList<Material>();
       public void addCrops()
  17. Maybe read the post in its entirety. You'll then notice that I'm trying to interact with crops without expressly defining them. Which, if you look, is exactly what you just did. You're replying saying I don't need it and you don't understand my use case at all. Please refrain from responding when you don't know what you're replying to. Thanks.
  18. Because I'm trying to get what a crop yields without expressly defining the Material myself in some helper class like I'm doing now. There is no API, that I am aware of, that allows you to figure out what a crop yields without knowing what specific crop it is and defining them yourself
  19. I want to know what items a crop drops when you break it, without having to map them myself.

    EDIT: The problem is that I'm not using the BlockBreakEvent, so I can't just check getDrops()

    EDIT 2: So the Block class has getDrops(), but I need to modify the seed amount. There's still no way to modify the seeds without defining what the seeds are myself