Communicating among events

The plugin works exactly as intended, but what if we have a change of heart and begin to miss the sound of rain? Alternatively, what if our town bursts into flames and it must be extinguished quickly? We do not want to limit our power as an administrator by denying ourselves the use of the /toggledownfall command. Next, we will listen for this command to be issued, and when it is issued, we will allow the weather to change. Ultimately, we will still be able to control the weather manually, but the weather will not start on its own.

Let's create another EventHandler method. This time, we will listen for a console command being sent so that we can set a Boolean flag, as follows:

@EventHandler (ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onPlayerCommand(PlayerCommandPreprocessEvent event) {
  //Check if the Player is attempting to change the weather
  if (event.getMessage().startsWith("/toggledownfall")) {
    //Verify that the Player has permission to change the weather
    if (event.getPlayer().hasPermission("minecraft.command.toggledownfall")) {
      //Allow the Rain to start for this occasion
      denyRain = false;
    }
  }
}

We will not actually be modifying this event at all. Therefore, the event priority will be set to MONITOR. We also want to ignore canceled events. The event that we will listen for is PlayerCommandPreprocessEvent, which will occur every time a player issues a command, whether they are for Minecraft, Bukkit, or another plugin. We only care about one command, namely /toggledownfall. So, the first if statement checks whether the message starts with /toggledownfall. If it is a different command, we will ignore it. As the event name suggests, this event occurs before the command is actually executed. Therefore, we must verify that a player has the permission to run the command. The permission node for the command is minecraft.command.toggledownfall. If these two conditions are met, then we want to allow rain to start on the next WeatherChangeEvent class. The second EventHandler method is completed by using the two if statements and setting a Boolean variable to false.

At this point, a light bulb will appear, informing you that the denyRain symbol cannot be found. When you click on the bulb, you can select Create Field denyRain in com.codisimus.norain.NoRain. This will automatically create a private variable called denyRain inside the class. Note the placement of the new line of code. It is outside the existing method blocks and yet still inside the class. This is important because it defines the variable's scope. The scope of a variable is where it can be accessed. The denyRain variable is private. Therefore, no other class, such as a class from another plugin, can modify it. However, within the NoRain class, all the methods can access it. This is useful because if the variable was declared within the curly braces of the onPlayerCommand method, we would not be able to see it from the onWeatherChange method.

Now that the plugin knows when we wish to allow the rain to start, we must slightly modify the onWeatherChange method to allow for such an exception. Currently, to cancel the event, we will call the setCancelled method with true as the parameter. If we were to pass false as a parameter, then the event would not be cancelled. The denyRain variable is equal to true when we wish to cancel the event. Therefore, rather than passing true or false, we can pass the value of denyRain. So, when denyRain is set to false, we will call setCancelled using the following line of code:

event.setCancelled(false);

At the end of the onWeatherChange method, we want to reset the value of denyRain to true. In this way, we can ensure that we allow the weather to change only once each time the /toggledownfall command is issued. The final code looks like this:

package com.codisimus.norain;

import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.weather.WeatherChangeEvent;
import org.bukkit.plugin.java.JavaPlugin;

public class NoRain extends JavaPlugin implements Listener {
  //This is a variable that our two methods will use to "communicate" with each other
  private boolean denyRain = true;

  @Override
  public void onEnable() {
    //Register all of the EventHandlers within this class
    getServer().getPluginManager().registerEvents(this, this);
  }

  @EventHandler (ignoreCancelled = true, priority =EventPriority.LOW)
  public void onWeatherChange(WeatherChangeEvent event) {
    if (event.toWeatherState()) { //Rain is trying to turn on
      //Cancel the event if denyRain is set to true
      event.setCancelled(denyRain);
    }
    //Reset the denyRain value until next time a Player issues the /toggledownfall command
    denyRain = true;
  }

  @EventHandler (ignoreCancelled = true, priority =EventPriority.MONITOR)
  public void onPlayerCommand(PlayerCommandPreprocessEvent event) {
    //Check if the Player is attempting to change the weather
    if (event.getMessage().startsWith("/toggledownfall")) {
      //Verify that the Player has permission to change the weather
      if (event.getPlayer().hasPermission("minecraft.command.toggledownfall")) { 
        //Allow the Rain to start for this occasion
        denyRain = false;
      }
    }
  }
}

Note that when we declare the Boolean denyRain method, we set its initial value to true.

This completes the NoRain plugin. Build the JAR file and test it out on your server. With this new version, you will be able to use the /toggledownfall command to stop and start rain.

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

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