Solved setAge(int age) method from Ageable not working

Discussion in 'Plugin Development' started by wand555, Feb 10, 2020.

  1. Offline

    wand555

    Hello,
    I'm trying to detect different types of crops. I already found a way using the BlockState, MaterialData, Crops and CropState, but the last three are deprecated and I thought that there is surely a better way to do this.
    The deprecated way to simulate growth:
    deprecated way (open)

    Code:java
    1. BlockState state = b.getState();
    2. MaterialData data = state.getData();
    3. if(data instanceof Crops) {
    4. Crops crops = (Crops) data;
    5. CropState cropState = crops.getState();
    6. System.out.println(cropState.getData());
    7. if(cropState != CropState.RIPE) {
    8. crops.setState(determineCropState(cropState, b, p));
    9. state.setData(crops);
    10. state.update();
    11. }
    12. }
    13.  
    14. private CropState determineCropState(CropState currentCropState, Block b, Player p) {
    15. double standard = 1/(Math.floor((25/2) + 1));
    16. double time = standard*growthFactor.get(p.getUniqueId());
    17. if(time > random.nextDouble()) {
    18. if(b.getType() == Material.BEETROOTS) {
    19. switch(currentCropState) {
    20. case SEEDED: return CropState.SMALL;
    21. case SMALL: return CropState.TALL;
    22. case TALL: return CropState.RIPE;
    23. default: return currentCropState;
    24. }
    25. }
    26. else {
    27. switch(currentCropState) {
    28. case SEEDED: return CropState.GERMINATED;
    29. case GERMINATED: return CropState.VERY_SMALL;
    30. case VERY_SMALL: return CropState.SMALL;
    31. case SMALL: return CropState.MEDIUM;
    32. case MEDIUM: return CropState.TALL;
    33. case TALL: return CropState.VERY_TALL;
    34. case VERY_TALL: return CropState.RIPE;
    35. default: return currentCropState;
    36. }
    37. }
    38. }
    39. return currentCropState;
    40. }


    except for the few extra code in there that is needed for the rest (not important for this problem), this is still a lot. After some further testing I found another way with bytes:
    bytes (open)

    Code:java
    1. public static void setCropState(BlockState state, CropState setTo) {
    2. MaterialData data = state.getData();
    3. if(data instanceof Crops) {
    4. Crops crops = (Crops) data;
    5. crops.setState(setTo);
    6. state.setData(crops);
    7. state.update();
    8. }
    9. }
    10.  
    11. public static void setCropState(BlockState state, byte offset) {
    12. MaterialData data = state.getData();
    13. if(data instanceof Crops) {
    14. Crops crops = (Crops) data;
    15. CropState cropState = crops.getState();
    16. if(inRange(cropState.getData(), offset)) {
    17. if(state.getType() == Material.BEETROOTS) {
    18. crops.setState(getRangeBeetroot(cropState.getData(), offset));
    19. state.setData(crops);
    20. state.update();
    21. }
    22. else {
    23. crops.setState(CropState.getByData((byte) (cropState.getData()+offset)));
    24. state.setData(crops);
    25. state.update();
    26. }
    27. }
    28. }
    29. }
    30.  
    31. private static boolean inRange(byte cropData, byte offset) {
    32. return (((byte) cropData+offset) >= 0 && ((byte) cropData+offset) <= 7);
    33. }
    34.  
    35. private static CropState getRangeBeetroot(byte cropData, byte offset) {
    36. switch ((byte) (cropData+offset)) {
    37. case 0: return CropState.SEEDED;
    38. case 1: return CropState.SEEDED;
    39. case 2: return CropState.SMALL;
    40. case 3: return CropState.SMALL;
    41. case 4: return CropState.TALL;
    42. case 5: return CropState.TALL;
    43. case 6: return CropState.RIPE;
    44. case 7: return CropState.RIPE;
    45. default: return CropState.getByData(cropData);
    46. }
    47. }


    However this also relies on deprecated methods.
    After some even further digging, I came up with this.
    not deprecated way (open)

    Code:java
    1. Block b2 = b1.getRelative(BlockFace.UP);
    2. if(b1.getBlockData() instanceof Farmland) {
    3. Farmland farmland = (Farmland) b1;
    4.  
    5. if(b2.getBlockData() instanceof CraftCrops) {
    6. CraftCrops crops = (CraftCrops) b2.getBlockData();
    7. }
    8. else if(b2.getBlockData() instanceof CraftCarrots) {
    9. CraftCarrots carrots = (CraftCarrots) b2.getBlockData();
    10. }
    11. else if(b2.getBlockData() instanceof CraftPotatoes) {
    12. CraftPotatoes potatoes = (CraftPotatoes) b2.getBlockData();
    13. }
    14. else if(b2.getBlockData() instanceof CraftBeetroot) {
    15. CraftBeetroot beetroots = (CraftBeetroot) b2.getBlockData();
    16. }
    17. else if(b2.getBlockData() instanceof CraftNetherWart) {
    18. CraftNetherWart netherwarts = (CraftNetherWart) b2.getBlockData();
    19. }
    20. else if(b2.getBlockData() instanceof CraftStem) {
    21. CraftStem stem = (CraftStem) b2.getBlockData();
    22. if(b2.getType() == Material.PUMPKIN_STEM) {
    23.  
    24. }
    25. else if(b2.getType() == Material.MELON_STEM) {
    26.  
    27. }
    28. }
    29. else if(b2.getBlockData() instanceof CraftBlockData) {
    30.  
    31. }
    32. }
    33. else {
    34. if(b2.getBlockData() instanceof CraftFluids) {
    35.  
    36. }
    37. else if(b2.getBlockData() instanceof CraftBlockData) {
    38. if(b2.getType() == Material.SUGAR_CANE) {
    39.  
    40. }
    41. }
    42. }


    This is not deprecated, because I'm using BlockData and it also works fine when I tested it. But now I tried changing the age for CraftCrops for example with the given setAge(int age) method, but it doesnt change anything. I already debugged everything and it reaches the code, it just doesnt change anything. I believe this has something to do with not updating BlockData (or whatever lol), because the deprecated method also requires updating the BlockState. The method setAge(int age) inherits from the interface Ageable and as the bukkit doc states, it should just work (at least there's no annotation saying it needs to be updated).
    I can get the state from BlockData, which is from the type IBlockData, which has an update method. However I couldnt find any information on IBlockData let alone how to use the update method.
    Any help is appreciated!
     
    Last edited: Feb 10, 2020
  2. Offline

    KarimAKL

    @wand555 This works for me:
    Code:Java
    1. Block block = ...; // Your block
    2. BlockData data = block.getBlockData();
    3.  
    4. if (data instanceof Ageable) {
    5. Ageable ageable = (Ageable) data;
    6. ageable.setAge(/*the age*/);
    7. data = ageable;
    8. }
    9.  
    10. block.setBlockData(data);
     
  3. Offline

    wand555

    @KarimAKL Thanks!
    It works even without data = ageable.
     
    KarimAKL likes this.
  4. Offline

    KarimAKL

    @wand555 Ah, that's my bad. I just copied some older code. :7
     

Share This Page