Accessing variables from another class

The MobEnhancer class is growing in size. There is no need to place all the code within a single class. This class is currently extending the JavaPlugin class as well as implementing both the Listener and CommandExecutor interfaces. The program will be easier to understand if we split these into three unique classes. This process is known as refactoring. Throughout the process of developing software, you will come across code that may be outdated or inefficient and needs to be updated. Changing the code in this way is referred to as refactoring. Don't be discouraged if you need to refactor your code in the future; it is a common occurrence in software development, and there are many reasons for it to happen.

  • You learned how to write more efficient code
  • API changes or new features require/allow code changes
  • The existing code is difficult to read or debug
  • A method/class has grown too large to manage
  • The purpose of the code has changed and it should now do something it was not originally intended to do

We will refactor MobEnhancer to split the code into three more manageable classes.

Create two new classes named MobSpawnListener and MobEnhancerReloadCommand. MobEnhancer will still be your main class. Therefore, it will still extend JavaPlugin. However, the two new classes will implement Listener and CommandExecutor respectively. Move the appropriate methods to their new classes, that is, onMobSpawn is an event handler and hence it belongs to the Listener class, and onCommand belongs to the CommandExecutor class. When moving the methods, you will see that several errors are introduced. This is because your methods no longer have access to the necessary methods and variables. Let's first address the MobEnhancerReloadCommand class, as it has only one error. This error occurs at the following line:

reloadConfig();

The reloadConfig method is in the JavaPlugin class, which is no longer merged with the CommandExector class. We need to access the JavaPlugin object from this separate class. The easiest way to do this is by using a static variable. If a variable or method is static, then it does not change across different instances of the class. This allows us to refer to the variable from a static context. You have done this before when using the Bukkit class. The methods that you called were static. Therefore, you could access them using the Bukkit class and not a unique Bukkit object.

To explain this better, let's imagine that you have a plugin that gives Minecraft players bank accounts. Therefore, you will have a class to represent a player's bank account. This class can be called PlayerAccount. You will have numerous PlayerAccount objects, one for each player on the server. Within this class, you may have a variable that defines a limit of how much money the account can hold. Let's name this variable accountLimit. If we want each account to have a maximum amount of money of 1000, then the accountLimit should be static. If we wish to increase the limit to 2000, then we set accountLimit to 2000 by using PlayerAccount.accountLimit = 2000;. Then, all the players now have an account limit of 2000. If we want some players to have a limit of 1000 and others to have a limit of 2000, then we should not use a static variable. Without accountLimit being static, if we set accountLimit to 2000 for instance A of PlayerAccount, it would still be 1000 for instance B of PlayerAccount.

Storing the plugin as a static variable within the main class will benefit us. Above your current variables, add a static JavaPlugin variable named plugin, as follows:

public class MobEnhancer extends JavaPlugin {
    //Static plugin reference to allow access from other classes.
    static JavaPlugin plugin;

We must also instantiate this variable within the onEnable method. This can simply be done using plugin = this;. Now, we can access the plugin instance by using MobEnhancer.plugin. Therefore, where we previously had reloadConfig();, we will now have MobEnhancer.plugin.reloadConfig(). This will fix the errors in MobEnhancerReloadCommand:

package com.codisimus.mobenhancer;

import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;

public class MobEnhancerReloadCommand implements CommandExecutor {
    @Override
    public boolean onCommand(CommandSender sender, Command command, String alias, String[] args) {
        MobEnhancer.plugin.reloadConfig();
        sender.sendMessage("MobEnhancer config has been reloaded");
        return true; //The command executed successfully
    }
}

MobSpawnListener requires a similar modification, as the plugin object is needed to call the getConfig method.

You will continue seeing errors in MobSpawnListener. It is attempting to access variables that are still in the main class. Let's move the mob armor variables to the Listener class, as follows:

public class MobSpawnListener implements Listener {
    private boolean giveArmorToMobs;
    private ItemStack zombieHolding;
    private ItemStack skeletonHolding;

We must also modify the reload method within MobEnhancer.java to match the new location of the variables. For example, instead of giveArmorToMobs, we should now have MobSpawnListener.giveArmorToMobs:

public void reloadConfig() {
    //Reload the config as this method would normally do
    super.reloadConfig();

    //Load values from the config now that it has been reloaded
    MobSpawnListener.giveArmorToMobs = getConfig().getBoolean("GiveArmorToMobs");
    MobSpawnListener.zombieHolding = getConfig().getItemStack("Zombie.   holding");
    MobSpawnListener.skeletonHolding = getConfig(). getItemStack("Skeleton.holding");
}

Even with this change, we will still be given an error, which reads giveArmorToMobs has private access in MobSpawnListener. Each variable is private, which means that they cannot be accessed from another class. We wish to be able to access them from the other classes. Hence, we will remove the private modifier. After doing so, we will be given yet another error. This new error reads non-static variable giveArmorToMobs cannot be referenced from a static context. This happens because the variables are not defined as static variables. Before you simply change these variables so that they can be static, ensure that it makes sense for them to be static. Refer to the earlier discussion about when static variables should be used. In this situation, we will only have one value of each of these variables. Hence, we do want to make them static, as shown in the following code:

public class MobSpawnListener implements Listener {
    static boolean giveArmorToMobs;
    static ItemStack zombieHolding;
    static ItemStack skeletonHolding;

There are only two lines remaining in the code that require our attention. These two lines are used to register the event listener and command executor. When calling the registerEvents method, two parameters are required. The first parameter is Listener, and the second one is Plugin. The this keyword references the plugin. Therefore, it is fine as the second parameter. However, for the first parameter, you must pass an instance of the Listener class. We have done this in Chapter 7, The Bukkit Event System, when creating the NoRain plugin. The same applies to the command executor. We must pass an instance of the MobEnhancerReloadCommand class:

//Register all of the EventHandlers
getServer().getPluginManager().registerEvents(new MobSpawnListener(), this);

//Register the Executor of the /mobenhancerreload command
getCommand("mobenhancerreload").setExecutor(new MobEnhancerReloadCommand());

This gets rid of all the errors that resulted from splitting the project into multiple classes.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.60.29