Skip to content

Plugin API

betterphp edited this page Apr 4, 2013 · 7 revisions

The core banning features are exposed to other plugins and their developers via the plugin API. As a plugin developer you are free to use the methods detailed on this page.

Dependency

You will need to add the MineBans plugin jar to your build path to be able to use it's resources in your code, how this is done varies per development environment. Maven users can add our repo

<repository>
	<id>jacekk-repo</id>
	<url>http://bukkit.jacekk.co.uk:8000/plugin/repository/everything/</url>
</repository>

and dependency

<dependency>
	<groupId>com.minebans</groupId>
	<artifactId>minebans</artifactId>
	<version>0.16</version>
	<scope>compile</scope>
</dependency>

The version number here should be replaced with the latest release build on BukkitDev.

Getting Hold of the API

Each plugin that makes use of the API must register itself with the MineBans plugin, this is used by the logging system to log which plugin has caused which actions.

To get an instance of the API to use you first need to get the MineBans plugin instance from the server and use the getPluginAPI method from it making sure to pass in the instance of your plugin. You can do all of this with the following code.

this.server = this.getServer();
this.manager = this.server.getPluginManager();

if (this.manager.isPluginEnabled("MineBans") == false){
	this.setEnabled(false);
	this.log.fatal("MineBans was not found on this server.");
	return;
}

this.api = ((MineBans) this.manager.getPlugin("MineBans")).getPluginAPI(this);

This example stores the api as a field in the main plugin class, the is generally the most convenient way to use it.

A Few Things to be Aware of

  1. All of the methods in the API will return true or false depending on if the action requested succeeded or not. These is one exception to this in the lookup method.
  2. Any method that calls the global API may not appear to work straight away. This is due to the way API requests are handled internally, each request is stacked and they are processed one at a time. The reason for this is to prevent a plugin that bans all players for example from opening hundreds of connections to the API. In reality the requests should complete within 40ms or so, but bear in mind that scheduling hundreds of requests may put the queue quite significantly behind.

Kicking

The following methods can be used to kick a player from the server, if you pluign is making use of the other API methods it is preferred that you use the kick method from the API also.

public boolean kickPlayer(Player player, String message);
public boolean kickPlayer(String playerName, String message);
public boolean kickPlayer(String playerName);
public boolean kickPlayer(Player player);

If the message is not provided it will default to You have been kicked from the server.

Exempt List

The exempt lists acts as a list of players that will be made exempt from the join checks meaning they can join even if they are over the servers limits.

You can check to see if a player is on the whitelist using either of the methods

public boolean isExempt(String playerName);
public boolean isExempt(Player player);

A player can be added to the exempt list using either of the methods

public boolean exemptPlayer(String playerName);
public boolean exemptPlayer(Player player)

or removed from it using

public boolean unExemptPlayer(String playerName);
public boolean unExemptPlayer(Player player);

Ban Lists

The three main ban lists can be gotten by using these methods. Each of these will return an ArrayList of playernames belonging to that list. These are actually copies of the internal list, meaning that modifying them will not result in the player being banned or unbanned.

public List<String> getLocallyBannedPlayers();
public List<String> getGloballyBannedPlayers();
public List<String> getTempBannedPlayers();

These is one more method available

public Map<String, BanType> getBannedPlayers();

This will return all of the players banned from the server, effectively combining the local, global and temporary list into one. Each entry has a key and value pair with the key being the players name and the value being their BanType. The BanType is an enum which can have the values BanType.LOCAL, BanType.GLOBAL or BanType.TEMP.

Banning

A ban has to be either local, temporary or global (more details below). you can check to see if a player is banned using ether of the methods

public boolean isBanned(String playerName);
public boolean isBanned(Player player);

Either of these will return true of false depending on if the player is banned or not.

Local

A local ban is one which is only in effect on the current server. They are never uploaded to the global database. This should be the most commonly used method in the API.

To locally ban a player you can use either of the following methods

public boolean locallyBanPlayer(String playerName);
public boolean locallyBanPlayer(Player player);

As an example you might want to simply implement a /ban command, in which you would most likely do

if (!plugin.api.locallyBanPlayer(args[0])){
	plugin.log.fatal("Failed to ban " + args[0] + " for some reason.");
}

Temporary

This method allows you to ban a player for a specific amount of time, the length of the ban may not be longer than 7 days since it is meant for very minor offences only.

The two methods you can use to temporally ban a player are

public boolean tempBanPlayer(String playerName, int banDuration);
public boolean tempBanPlayer(Player player, int banDuration);

As an example, you could have a player banned for 15 minutes when they die (perhaps a little harsh)

@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerDeath(PlayerDeathEvent event){
	plugin.api.tempBanPlayer(event.getPlayer(), 900);
}

Global

Global bans are handled much more strictly, since they affect all servers using the system. You must specify a reason for the ban and the name of the player to be made responsible for it.

The two methods you could use to globally ban a player are

public boolean globallyBanPlayer(String playerName, String issuedBy, BanReason reason);
public boolean globallyBanPlayer(Player player, String issuedBy, BanReason reason);

The first parameter here is the same as it could be for the other methods, the second one should be a string containing the name of the player that issued the ban. The final parameter is the reason the ban is being issued, this should be BanReason.X where X is the reason. A full list of the reasons available can be seen in the source of BanReason.java.

As an example you may want to make your ban command ban the player for griefing, probably not the best idea since the other reasons may be more fitting, but it will do as an example.

if (!plugin.api.globallyBanPlayer(args[0], sender.getName(), BanReason.GRIEF)){
	plugin.log.fatal("Failed to ban " + args[0] + " for some reason.");
}

The MineBans plugin will handle the evidence collecting.

Unbanning

There are method available to remove any bans that a player might have, these are

public boolean unBanPlayer(String playerName, String issuedBy);
public boolean unBanPlayer(Player player, String issuedBy);

These may not be very convenient since you need to specify the player issuing the request to be used if the ban is global.

Local

Removing a local ban can be done using either of the methods

public boolean unLocalBanPlayer(String playerName);
public boolean unLocalBanPlayer(Player player);

Temporary

Removing a temporary ban can be done using either of the methods

public boolean unTempBanPlayer(String playerName);
public boolean unTempBanPlayer(Player player);

Global

Removing a global ban can be done using either of the methods

public boolean unGlobalBanPlayer(String playerName, String issuedBy);
public boolean unGlobalBanPlayer(Player player, String issuedBy);

The issuedBy parameter here is the same as for the global ban method above also note that it does not have to be the player that originally issued the ban.

Lookup

You can get data from the global API on a player's bans. Because this method has to wait for the API to respond, it will not return anything. The request is done on a separate thread and must first wait for any other requests to complete. This means you have to pass in a callback, this is simply a method which will be called if and when the API has responded.

Player lookups can be done using either of the following methods

public void lookupPlayer(String playerName, String issuedBy, PluginAPIResponseCallback callback);
public void lookupPlayer(Player player, String issuedBy, PluginAPIResponseCallback callback);

The first two parameters are the same as for the global ban method the final parameter must be an instance of a class which implements the PluginAPIResponseCallback interface. It must define two methods, onSuccess and onFailure. The onSuccess method must accept one parameter, this being a PlayerBanData object and the onFailure method must accept an Exception as its parameter. The PlayerBanData object handles the processing of the API response and provides a number of methods to get the information, these are

public HashMap<String, Long> getSummary();
public Long getTotal();
public Long getLast24();
public Long getRemoved();
public HashMap<BanReason, HashMap<BanSeverity, Long>> getBans();
public Set<BanReason> getBanReasons();
public Integer getTotalRulesBroken();
public Long get(BanReason reason, BanSeverity severity);
public Long get(Integer reasonId, BanSeverity severity);
public Long getTotal(Integer reasonId);
public Long getTotal(BanReason reason);
public Long getTotal(BanSeverity severity);

An example is probably the best way to understand how to use this, so here is how you could implement a /lookupme command which will show the player a summary of their bans.

final String playerName = sender.getName();

plugin.api.lookupPlayer(playerName, "console", new PluginAPIResponseCallback(){
	
	public void onSuccess(PlayerBanData data){
		Player player = plugin.getServer.getPlayer(playerName);
		
		// They might have signed out by the time the API responds
		if (player != null){
			player.sendMessage(ChatColor.GREEN + "Total bans on record: " + playerData.getTotal());
			player.sendMessage(ChatColor.GREEN + "Bans in the last 24 hours: " + playerData.getLast24());
			player.sendMessage(ChatColor.GREEN + "Bans that have been removed: " + playerData.getRemoved());
		}
	}
	
	public void onFailure(Exception e){
		plugin.log.fatal("Failed to lookup " + args[0]);
		e.printStackTrace();
	}
	
});

The use of console here as the players name means that the server admin will be made responsible for this request, you cannot use this for global bans.

Events

As well as the PluginAPI you may use some of the custom events that MineBans uses to have somethign happen on an event.

PlayerBanEvent

This is called when ever a player is banned from the server, this includes all types of ban. Since this is such a broad event you will not be able to get specific information such as the BanReason since that would not exist for local bans. All that can be got from this event is the name of the player banned and the ban type.

As an example, you could use this to implement a ban logging plugin to log players bans to a separate log file.

@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerBan(PlayerBanEvent event){
	StringBuilder line = new StringBuilder();
	BanType type = event.getBanType();
	
	line.append(event.getPlayerName());
	line.append(" has been ");
	
	if (type == BanType.LOCAL){
		line.append("locally ");
	]else if (type == BanType.TEMP){
		line.append("temporarily ");
	}else if (type == BanType.GLOBAL){
		line.append("globally ");
	}
	
	line.append("banned");
	
	this.writeLineToFile(line.toString());
}

PlayerGlobalBanEvent, PlayerLocalBanEvent and PlayerTempBanEvent

These are essentially more specific version of the above generally ban event and when combined they provide more information. A better way to implement the above example would be using a combination of these.

@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerGlobalBan(PlayerGlobalBanEvent event){
	StringBuilder line = new StringBuilder();
	
	line.append(event.getPlayerName());
	line.append(" has been globally banned for ");
	line.append(event.getReason().getDescription());
	
	this.writeLineToFile(line.toString());
}

@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerLocalBan(PlayerLocalBanEvent event){
	StringBuilder line = new StringBuilder();
	
	line.append(event.getPlayerName());
	line.append(" has been locally banned");
	
	this.writeLineToFile(line.toString());
}

@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerTempBan(PlayerTempBanEvent event){
	StringBuilder line = new StringBuilder();
	
	line.append(event.getPlayerName());
	line.append(" has been temporarily banned for ");
	line.append(event.getBanDuration());
	line.append(" seconds");
	
	this.writeLineToFile(line.toString());
}

In reality you would probably want to format the ban duration into a number of hours or minutes.

PlayerConnectionAllowedEvent

This is called when a player passes all of the checks that MineBans does and is allowed to join the server. This could be used to show a simple welcome message for example.

@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerConnectionAllowedEvent(PlayerConnectionAllowedEvent event){
	plugin.getServer().broadcastMessage(ChatColor.DARK_PURPLE + event.getPlayerName() + " has joined the server :)");
}

There are three situations that can cause this event to be called, you can find out why the player was allowed to connect by checking the CnnectionAlloedReason which can be found using the method

public ConnectionAllowedReason getReason();

PlayerConnectionDeniedEvent

This is the opposite of the above event, it is called whenever a player is prevented from joining. There are a number of possible causes for this, you can find out why the player was blocked by checking the ConnectionDeniedReason which can be found using the method

public ConnectionDeniedReason getReason();

Note that ConnectionDeniedReason.OTHER may be the result of this which suggests that the cause was a check done by an external plugin.

PlayerUnbanEvent

This is called whenever a player's ban is removed from the server, this covers any type of ban. The players name can be got using the getPlayerName() method and the type of ban being removed from the getBanType() method.

As an example you could extend the logging example above for include players being unbanned as well.

@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerUnban(PlayerUnbanEvent event){
	StringBuilder line = new StringBuilder();
	BanType type = event.getBanType();
	
	line.append(event.getPlayerName());
	line.append(" has had their ");
	
	if (type == BanType.LOCAL){
		line.append("local ");
	]else if (type == BanType.TEMP){
		line.append("temporary ");
	}else if (type == BanType.GLOBAL){
		line.append("global ");
	}
	
	line.append("ban removed");
	
	this.writeLineToFile(line.toString());
}

PlayerExemptEvent

This is called when a player is added to the exempt list, the name of the player can be found using the getPlayerName() method.

PlayerUnExemptEvent

This is called when a player is removed from the exempt list, similarly to the above event the player's name can be found from the getPlayerName() method.

PlayerLoginDataEvent

This is called when the player info is fetched from the API as they join, you can use this to add additional restrictions based on the data.

The following methods are available from the event

public String getPlayerName();
public String getPlayerAddress();
public PlayerJoinData getJoinData();
public Boolean isConnectionPrevented();
public ConnectionDeniedReason getReason();
public String getKickMessage();
public String getLogMessage();
public void setPreventConnection(Boolean prevent);
public void setReason(ConnectionDeniedReason reason);
public void setKickMessage(String message);
public void setLogMessage(String message);

You can listen for this even and use it to prevent a player's connection, as an example this is how the group ban feature is implemented

public class GroupBanListener implements Listener {
	
	@EventHandler(priority = EventPriority.NORMAL)
	public void onPlayerLoginData(PlayerLoginDataEvent event){
		if (event.getJoinData().getBanData().getTotalGroupBans() > 0){
			event.setPreventConnection(true);
			event.setReason(ConnectionDeniedReason.GROUP_BAN);
			event.setKickMessage(ConnectionDeniedReason.GROUP_BAN.getKickMessage());
			event.setLogMessage(ConnectionDeniedReason.GROUP_BAN.getLogMessage());
		}
	}
	
}

It is probably easiest to think of isConnectionPrevented and setPreventConnection in the same way as Bukkit's isCancelled and setCancelled. The rest of the methods are optional (but highly recommended).