Using the Arrow Registry

Jun 1, 2016
Using the Arrow Registry
  • Using the Arrow Registry

    One of the key mechanics of AlchemicalArrows is the ArrowRegistry class. If you have read the Creating an Alchemical Arrow page, you will know that the ArrowRegistry class has a couple of static methods to register your own custom arrows and allow the plugin to recognize that they are externally created. However, there is also a secondary use to this which contains a set of non-static methods used to "track" all living arrows on the server. This is what actually allows the plugin to determine what effect should be given to the arrow upon landing.

    It is suggested that you do not use this class unless absolutely necessary, for example, requiring to unregister an arrow from its effects. You could cancel all arrow effects if the methods within this class aren't used properly. Granted, your plugin may not be used all that often if that's your goal.


    Retrieving the ArrowRegistry Class

    To retrieve the ArrowRegistry class, you must access it through the main AlchemicalArrows class. Quite simple, actually. There is a public (non-static) method in the AlchemicalArrows class which allows you to obtain the main ArrowRegistry class and manipulate it to your liking. It's suggested to call this method once, and keep an instance variable in your main class, though not absolutely necessary.

    Code (Java):
    public class MainClass extends JavaPlugin{
     
        private ArrowRegistry registry;
     
        @Override
        public void onEnable(){
            registry = AlchemicalArrows.getPlugin().getArrowRegistry();
        }
    }
    You now have an instance of the ArrowRegistry class, free to use to your liking. Let's continue on with how to actually use the registry and most of the methods that may come of use to you.


    Registering Alchemical Arrows

    From this point on, it may get confusing. A lot of the methods use the term "Register", though do not confuse them with the registration of the static ArrowRegistry.registerAlchemicalArrow() methods. Javadocs are available on all methods in this class if you are confused as to what they do.

    So let's say we want to go against the AlchemicalArrows API, for whatever reason. Perhaps you're doing something special or require a special object in order to shoot your AlchemicalArrow. This is where the ArrowRegistry#registerAlchemicalArrow() method comes in handy. No, not the static one, the one with only one AlchemicalArrow parameter. In order to use this however, we require an instance of an AlchemicalArrow (Not the .class, but an instance of one). This is where you would use "new YourCustomArrowClass(Arrow)" (Or one of the already pre-created classes in the AlchemicalArrows project).

    As an example, I will register an EarthArrow (this arrow is built in to the AlchemicalArrows plugin) in a ProjectileLaunchEvent listener. This will result in all arrows being registered to EarthArrow.

    Code (Java):
    public class MainClass extends JavaPlugin implements Listener{
     
        private ArrowRegistry registry;
     
        @Override
        public void onEnable(){
            registry = AlchemicalArrows.getPlugin().getArrowRegistry();
            Bukkit.getPluginManager().registerEvents(this, this);
        }

        @EventHandler
        public void onShootArrow(ProjectileLaunchEvent event){
            if (event.getProjectile() instanceof Arrow){
                EarthArrow earthArrow = new EarthArrow((Arrow) event.getProjectile())
                registry.registerAlchemicalArrow(earthArrow);
            }
        }
    }
    There you go! You've now just force registered a new EarthArrow as soon as any arrow projectile is shot! Simple as that. Granted, not all that useful, but hey, it's available if you need it.


    Getting Alchemical Arrows

    So what if you need to grab an instance of a specific alchemical arrow? Of course, you'd use the ArrowRegistry. There are a couple of methods to retrieve an instance of an alchemical arrow. If you were curious, yes, this is how AlchemicalArrows grabs an instance of your custom alchemical arrow upon hitting an entity or the ground. Let's use the same code above to grab that Earth Arrow right back (Even though we already have it... but you know what? Whatever).

    Code (Java):
    public class MainClass extends JavaPlugin implements Listener{
     
        private ArrowRegistry registry;
     
        @Override
        public void onEnable(){
            registry = AlchemicalArrows.getPlugin().getArrowRegistry();
            Bukkit.getPluginManager().registerEvents(this, this);
        }

        @EventHandler
        public void onShootArrow(ProjectileLaunchEvent event){
            if (event.getProjectile() instanceof Arrow){
                EarthArrow earthArrow = new EarthArrow((Arrow) event.getProjectile())
                registry.registerAlchemicalArrow(earthArrow);
             
                //Now let's grab the arrow from the registry
                AlchemicalArrow aa = registry.getAlchemicalArrow((Arrow) event.getProjectile()); //By Arrow instance
                AlchemicalArrow aa2 = registry.getAlchemicalArrow((Arrow) event.getProjectile().getUniqueId()); //By UUID
            }
        }
    }
    As you can see, there are two ways to retrieve an alchemical arrow from the registry. You have the option of querying by either instance of an Arrow, or by Universally Unique Identification (UUID). But... what happens if they aren't actually registered alchemical arrows? Well in this case, they are because we had just registered them before hand, but otherwise it's suggested that you use another method before actually grabbing the instances.

    Code (Java):
    public class MainClass extends JavaPlugin implements Listener{
     
        private ArrowRegistry registry;
     
        @Override
        public void onEnable(){
            registry = AlchemicalArrows.getPlugin().getArrowRegistry();
            Bukkit.getPluginManager().registerEvents(this, this);
        }

        @EventHandler
        public void onShootArrow(ProjectileLaunchEvent event){
            if (event.getProjectile() instanceof Arrow){
                EarthArrow earthArrow = new EarthArrow((Arrow) event.getProjectile())
                registry.registerAlchemicalArrow(earthArrow);
             
                //Now let's grab the arrow from the registry
                if (registry.isAlchemicalArrow((Arrow) event.getProjectile())){
                    AlchemicalArrow aa = registry.getAlchemicalArrow((Arrow) event.getProjectile()); //By Arrow instance
                    AlchemicalArrow aa2 = registry.getAlchemicalArrow((Arrow) event.getProjectile().getUniqueId()); //By UUID
                }
            }
        }
    }
    Depending on whether this is an alchemical arrow or not, it will return true or false. Much like the getAlchemicalArrow() method, there is a method that accepts Arrow instance, and one that accepts UUID. It's really up to you whether you want to use one or the other.


    Unregistering Alchemical Arrows

    Now, this is not one you have to check for as it will not throw a NullPointerException, though regardless these methods are still deprecated. They are usable, but you have to be cautious knowing that they may throw a ConcurrentModificationException if used at the wrong time. These are typically meant to be used shortly after registration of an arrow occurs. The reason for the ConcurrentModificationException is due to the way particle effects are handled. There should be no true reason to unregister an alchemical arrow manually, as AlchemicalArrows does that automatically once the life of the arrow comes to a halt. No memory leak issues will occur

    There will be no code exemplifications for this method, as they are once again deprecated, but if you would like to use them, feel free to look at the javadoc documentation listed for the method and use it with caution.


    Retrieving all Alchemical Arrows

    The last part about the ArrowRegistry class, is retrieving all the alchemical arrows currently registered by the plugin. There may be a time in which you need to loop through all alchemical arrows, and this is how you would do it.

    Code (Java):
    public class MainClass extends JavaPlugin{
     
        private ArrowRegistry registry;
     
        @Override
        public void onEnable(){
            registry = AlchemicalArrows.getPlugin().getArrowRegistry();
            for (AlchemicalArrow arrow : registry.getRegisteredArrows()){
                /* Do whatever you want to any of the AlchemicalArrows
                 * If you truly wanted to, you could force all arrows to play their "onHitBlock" methods
                 *         i.e.: arrow.onHitBlock();
                 */

            }
        }
    }
    With this, you are free to modify whatever you would like about any arrow currently in the world. Forcefully fire their methods, check their boolean return methods, delete them, or do whatever you want. It's completely up to you, but I once again suggest that you do not use this, but it is available if deemed necessary to your requirements.
  • Loading...
  • Loading...