[Util] Beacon BlockState API (Sort of)

Discussion in 'Resources' started by foodyling, Aug 2, 2013.

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

    foodyling

    As far as I know, there is currently no way to set what potion effects a beacon can give off (since the interface of the Beacon blockstate is empty). I've created this quick class to essentially be able to set the effects of a Beacon and get the data for the beacon. (I'm going to cry if there already was a way I missed)
    Code (Text):
    1. import java.lang.reflect.Field;
    2. import java.lang.reflect.Method;
    3.  
    4. import org.bukkit.Bukkit;
    5. import org.bukkit.block.Block;
    6. import org.bukkit.block.BlockState;
    7. import org.bukkit.entity.LivingEntity;
    8. import org.bukkit.inventory.ItemStack;
    9. import org.bukkit.potion.PotionEffectType;
    10.  
    11. /**
    12. *
    13. * @author Foodyling
    14. */
    15. public class BeaconState {
    16.     public static class ReflectionUtil {
    17.         private static final String MC_VERSION = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
    18.  
    19.         public static Class<?> forClassName(String name) {
    20.             try {
    21.                 return Class.forName(name.replace("%MC_VERSION%", MC_VERSION));
    22.             } catch (Throwable error) {
    23.                 return null;
    24.             }
    25.         }
    26.  
    27.         public static Method getMethod(Class<?> clazz, String methodName, Class<?>... params) {
    28.             try {
    29.                 return clazz.getMethod(methodName, params);
    30.             } catch (Throwable error) {
    31.                 return null;
    32.             }
    33.         }
    34.  
    35.         public static Field getField(Class<?> clazz, String fieldName) {
    36.             try {
    37.                 return clazz.getDeclaredField(fieldName);
    38.             } catch (Throwable error) {
    39.                 return null;
    40.             }
    41.         }
    42.     }
    43.    
    44.     private static final Class<?> beaconState = ReflectionUtil.forClassName("net.minecraft.server.%MC_VERSION%.TileEntityBeacon"),
    45.                                   craftBeacon = ReflectionUtil.forClassName("org.bukkit.craftbukkit.%MC_VERSION%.block.CraftBeacon"),
    46.                                   entityHuman = ReflectionUtil.forClassName("net.minecraft.server.%MC_VERSION%.EntityHuman");
    47.    
    48.     private static final Field tileEntityBeacon = ReflectionUtil.getField(craftBeacon, "beacon"),
    49.                               primary = ReflectionUtil.getField(beaconState, "f"),
    50.                               secondary = ReflectionUtil.getField(beaconState, "g");
    51.    
    52.     private static final Method getName = ReflectionUtil.getMethod(beaconState, "getName"),
    53.                                 setName = ReflectionUtil.getMethod(beaconState, "a", String.class),
    54.                                 tier = ReflectionUtil.getMethod(beaconState, "l"),
    55.                                 getItem = ReflectionUtil.getMethod(beaconState, "getItem", int.class),
    56.                                 setItem = ReflectionUtil.getMethod(beaconState, "setItem", int.class, ItemStack.class);
    57.    
    58.     static {
    59.         tileEntityBeacon.setAccessible(true);
    60.         primary.setAccessible(true);
    61.         secondary.setAccessible(true);
    62.     }
    63.    
    64.     private final Block block;
    65.     private final Object blockState;
    66.    
    67.     public BeaconState(Block block) {
    68.         this(block.getState());
    69.     }
    70.    
    71.     public BeaconState(BlockState state) {
    72.         if (craftBeacon.isInstance(state)) {
    73.             try {
    74.                 this.block = state.getBlock();
    75.                 this.blockState = tileEntityBeacon.get(craftBeacon.cast(state));
    76.             } catch (Throwable error) {
    77.                 throw new IllegalArgumentException("BlockState must be a instance of org.bukkit.craftbukkit.block.CraftBeacon");              
    78.             }
    79.         } else {
    80.             throw new IllegalArgumentException("BlockState must be a instance of org.bukkit.craftbukkit.block.CraftBeacon");
    81.         }
    82.     }
    83.    
    84.     public static BeaconState asBeacon(Block block) {
    85.         return new BeaconState(block);
    86.     }
    87.    
    88.     public static BeaconState asBeacon(BlockState state) {
    89.         return new BeaconState(state);
    90.     }
    91.    
    92.     public Block getBlock() {
    93.         return block;
    94.     }
    95.    
    96.     public String getName() {
    97.         try {
    98.             return (String) getName.invoke(blockState);
    99.         } catch (Throwable error) {
    100.             return null;
    101.         }
    102.     }
    103.    
    104.     public void setName(String name) {
    105.         try {
    106.             setName.invoke(blockState, name);
    107.         } catch (Throwable error) {
    108.             error.printStackTrace();
    109.         }
    110.     }
    111.    
    112.     public PotionEffectType getPrimary() {
    113.         try {
    114.             return PotionEffectType.getById(primary.getInt(blockState));
    115.         } catch (Throwable error) {
    116.             return null;
    117.         }
    118.     }
    119.    
    120.     public PotionEffectType getSecondary() {
    121.         try {
    122.             return PotionEffectType.getById(secondary.getInt(blockState));
    123.         } catch (Throwable error) {
    124.             return null;
    125.         }
    126.     }
    127.    
    128.     public void setPrimary(PotionEffectType type) {
    129.         try {
    130.             primary.setInt(blockState, type.getId());
    131.         } catch (Throwable error) {
    132.             error.printStackTrace();
    133.         }
    134.     }
    135.    
    136.     public void setSecondary(PotionEffectType type) {
    137.         try {
    138.             secondary.setInt(blockState, type.getId());
    139.         } catch (Throwable error) {
    140.             error.printStackTrace();
    141.         }
    142.     }
    143.    
    144.     public void setBoth(PotionEffectType type) {
    145.         setPrimary(type);
    146.         setSecondary(type);
    147.     }
    148.    
    149.     public int getTier() {
    150.         try {
    151.             return ((Integer) tier.invoke(blockState)).intValue();
    152.         } catch (Throwable error) {
    153.             error.printStackTrace();
    154.             return 0;
    155.         }
    156.     }
    157.    
    158.     public ItemStack getItem() {
    159.         try {
    160.             return (ItemStack) getItem.invoke(blockState, 0);
    161.         } catch (Throwable error) {
    162.             return null;
    163.         }
    164.     }
    165.    
    166.     public void setItem(ItemStack stack) {
    167.         try {
    168.             setItem.invoke(blockState, 0, stack);
    169.         } catch (Throwable error) {
    170.        
    171.         }
    172.     }
    173.    
    174.     public boolean applicableFor(LivingEntity entity) {
    175.         if (entityHuman.isInstance(entity)) {
    176.             return entity.getLocation().distanceSquared(block.getLocation()) <= 4096;
    177.         }
    178.         return false;
    179.     }
    180. }
    To use this, you must either have a Block or a BlockState (it will throw a IllegalArgumentException if it's not a Beacon). Here's an example of how to get a Beacon BlockState
    Code (Text):
    1.  
    2. // There are two ways to get the 'BlockState' either using BeaconState.asBeacon(block) or create a new instance new BeaconState(block)
    3. BeaconState state = new BeaconState(block);
    4. // Set the effect for both, which makes it a level 2 effect
    5. state.setBoth(PotionEffectType.SLOW);
    6.  
    7. // Set the primary effect
    8. state.setPrimary(PotionEffectType.HEALTH_BOOST);
    9. // Set a secondary
    10. state.setSecondary(PotionEffectType.ABSORPTION);
    11.  
    12. // Get an effect, returns null if empty or an error occures
    13. state.getPrimary();
    14.  
    15. // Checks if a living entity is elgible for a effect
    16. state.applicableFor(entity);
    17.  
    18. // Get the tier of the beacon
    19. state.getTier();
    20.  
     
  2. I believe that the tuxtwolib has this ability (from the prettyscarylib).
     
  3. Offline

    foodyling

    Ultimate_n00b *Well* you wouldn't need another dependency if you only wanted to change the beacon effects.
     
  4. No, I understand the reasoning for you posting here. I just thought I would mention it for the people who already have the dependency.
     
    foodyling likes this.
Thread Status:
Not open for further replies.

Share This Page