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.
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.
3.145.60.29