Overhauled the blacklist system.

- The blacklist's method of preventing notification repeats is now better, instead waiting 3 seconds before notifying again (before it didn't notify again at all unless the user started using another blocked action).
- To give users the ability to receive notifications, the command to give permission to has been changed to /worldguardnotify, although the old one (that was never mentioned anywhere) still works.
- Water and lava buckets are now psuedo-blocked using an unreliable method that risks the stability of your server (no other plugin does it better though). Use it as your own risk.
- Added on item drop and on item use (i.e. chest) events.
- Chests, signs, and furnaces can now be blocked better with the blacklist system.
- The event names in the blacklist configuration have changed but the old event names should still work. The new names should make "more sense."
- A new "ban" action has been added to the blacklist.
- Action messages have been improved, now longer saying "destroyed" for everything.
- Logging to file has been completely changed, allowing you to use the date and time and the player's username in the log filename. It no longer rotates log files based on size, however.
- Logging to database is now supported.
This commit is contained in:
sk89q 2010-11-19 20:03:19 -08:00
parent 47a4046d47
commit 1859fc5db2
14 changed files with 1794 additions and 280 deletions

View File

@ -1,3 +1,33 @@
1.2
- Blacklist system has been overhauled. Check README.txt for changed
configuration settings!
- The blacklist's method of preventing notification repeats is now better,
instead waiting 3 seconds before notifying again (before it didn't
notify again at all unless the user started using another blocked
action).
- To give users the ability to receive notifications, the command to give
permission to has been changed to /worldguardnotify, although the
old one (that was never mentioned anywhere) still works.
- Water and lava buckets are now psuedo-blocked using an unreliable
method that risks the stability of your server (no other plugin
does it better though). Use it as your own risk.
- Added on item drop and on item use (i.e. chest) events.
- Chests, signs, and furnaces can now be blocked better with the
blacklist system.
- The event names in the blacklist configuration have changed but the old
event names should still work. The new names should make "more sense."
- A new "ban" action has been added to the blacklist.
- Action messages have been improved, now longer saying "destroyed"
for everything.
- Logging to file has been completely changed, allowing you to use
the date and time and the player's username in the log filename. It
no longer rotates log files based on size, however.
- Logging to database is now supported.
- Tools can now be destroyed on drop to alleviate the durability cheat.
You can do this with either with the blacklist or with the
'item-drop-blacklist' configuration option. The configuration option
prints more friendly messages than the 'tell' action of blacklists.
1.1.2
- Block lag fix: Snow and glass should no longer drop items.
- Block lag fix: Block object now reset after hook call.

View File

@ -53,30 +53,11 @@ WorldGuard on your server. You can either restart your server or use
the server when s/he logs in, the other player will be kicked with
an informative message. The inventory will have been saved before
the new session starts.
- blacklist-log-console (def. true)
For log actions, print to console as well.
- blacklist-log-file (no default)
File to log to. Log files are automatically rotated based on size, and
you can use these patterns in the path:
%t the system temporary directory
%h the value of the "user.home" system property
%g the generation number to distinguish rotated logs
%u a unique number to resolve conflicts
%% translates to a single percent sign "%"
There is no way to put the date in the filename or rotate by date.
- blacklist-log-file-limit (def. 5242880)
Size in bytes before the log file is rotated.
- blacklist-log-file-count (def. 10)
Number of log files to keep in rotation at maximum.
- block-tnt (def. false)
Block TNT explosions. TNT will still explode client-side but the blocks
will be "restored" in a few seconds afterwards.
- block-lighter (def. false)
Block flint and steel fires. Those with access to the commands
/uselighter or /lighter can bypass this. /uselighter is not a real
@ -100,9 +81,69 @@ WorldGuard on your server. You can either restart your server or use
to disable this feature. Enabling disable-all-fire-spread will
override this function.
- item-drop-blacklist (no default)
List of block names/IDs to destroy on drop. This can alleviate the
durability cheat that allows you to drop your tools to fix their
durability. You can also enforce this with the blacklist but
this is an easier way to do it (this way also prints a more
friendly message than if you used the 'tell' action of the blacklist).
- block-lag-fix (def. false)
Attempts to fix block lag.
- log-console (def. true)
For blacklist log actions, print to console.
- log-file (def. false)
For blacklist log actions, log to file.
- log-file-path (def. "worldguard/logs/%Y-%m-%d.log")
Log blacklist events to file. You can use these patterns in the path:
%Y the year (YYYY)
%m the month (MM)
%d the day (DD)
%W the week of the year (00-52)
%H 24-hour time (HH)
%h 12-hour time (HH)
%i the minute (mm)
%s the second (ss)
%u the user's name
%% translates to a single percent sign "%"
The files are not automatically rotated if they get large so you should
perhaps put a week in the filename at least.
Escape backslashes with another backslash, like so:
C:\path\to\log.txt -> C:\\path\\to\\log.txt
- log-file-open-files (def. 10)
The number of log files to keep open at once. Unless you use dynamic
patterns in the path, the value of this variable won't matter. However,
if, for example, you use a player's username in the filename and you
have many users who cause logged events to occur, files would have
to be opened for each user and this parameter would matter.
- log-database (def. false)
Log blacklist events to database.
- log-database-dsn (def. "jdbc:mysql://localhost:3306/minecraft")
Connection string. A string to use for MySQL would be:
jdbc:mysql://localhost:3306/minecraft
The "minecraft" part at the end is the database name.
Escape colons with a backslash, like so:
jdbc:mysql://localhost:3306/minecraft
->
jdbc\:mysql\://localhost\:3306/minecraft
- log-database-user (def. "root")
Database username.
- log-database-pass (def. "")
Database password.
- log-database-table (def. "blacklist_events")
Database table to use.
Blacklists
----------

308
src/Blacklist.java Normal file
View File

@ -0,0 +1,308 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.io.*;
/**
*
* @author sk89q
*/
public class Blacklist {
/**
* Logger.
*/
private static final Logger logger = Logger.getLogger("Minecraft.WorldGuard");
/**
* List of entries by block ID.
*/
private Map<Integer,List<BlacklistEntry>> blacklist
= new HashMap<Integer,List<BlacklistEntry>>();
/**
* Logger.
*/
private BlacklistLogger blacklistLogger = new BlacklistLogger();
/**
* Returns whether the list is empty.
*
* @return
*/
public boolean isEmpty() {
return blacklist.isEmpty();
}
/**
* Get the entries for an item or list.
*/
public List<BlacklistEntry> getEntries(int id) {
return blacklist.get(id);
}
/**
* Get the logger.
*
* @return
*/
public BlacklistLogger getLogger() {
return blacklistLogger;
}
/**
* Called on block destruction. Returns true to let the action pass
* through.
*
* @param block
* @param player
* @return
*/
public boolean onDestroy(final Block block, final Player player) {
List<BlacklistEntry> entries = getEntries(block.getType());
if (entries == null) {
return true;
}
boolean ret = true;
for (BlacklistEntry entry : entries) {
if (!entry.onDestroy(block, player)) {
ret = false;
}
}
return ret;
}
/**
* Called on left click. Returns true to let the action pass through.
*
* @param item
* @param player
* @return
*/
public boolean onDestroyWith(int item, Player player) {
List<BlacklistEntry> entries = getEntries(item);
if (entries == null) {
return true;
}
boolean ret = true;
for (BlacklistEntry entry : entries) {
if (!entry.onDestroyWith(item, player)) {
ret = false;
}
}
return ret;
}
/**
* Called on right click. Returns true to let the action pass through.
*
* @param item
* @param player
* @return
*/
public boolean onCreate(int item, Player player) {
List<BlacklistEntry> entries = getEntries(item);
if (entries == null) {
return true;
}
boolean ret = true;
for (BlacklistEntry entry : entries) {
if (!entry.onCreate(item, player)) {
ret = false;
}
}
return ret;
}
/**
* Called on right click upon. Returns true to let the action pass through.
*
* @param item
* @param player
* @return
*/
public boolean onUse(Block block, Player player) {
List<BlacklistEntry> entries = getEntries(block.getType());
if (entries == null) {
return true;
}
boolean ret = true;
for (BlacklistEntry entry : entries) {
if (!entry.onUse(block, player)) {
ret = false;
}
}
return ret;
}
/**
* Called on right click upon. Returns true to let the action pass through.
*
* @param item
* @param player
* @return
*/
public boolean onSilentUse(Block block, Player player) {
List<BlacklistEntry> entries = getEntries(block.getType());
if (entries == null) {
return true;
}
boolean ret = true;
for (BlacklistEntry entry : entries) {
if (!entry.onSilentUse(block, player)) {
ret = false;
}
}
return ret;
}
/**
* Called on drop. Returns true to let the action pass through.
*
* @param item
* @param player
* @return
*/
public boolean onDrop(int item, Player player) {
List<BlacklistEntry> entries = getEntries(item);
if (entries == null) {
return true;
}
boolean ret = true;
for (BlacklistEntry entry : entries) {
if (!entry.onDrop(item, player)) {
ret = false;
}
}
return ret;
}
/**
* Load the blacklist.
*
* @param file
* @return
* @throws IOException
*/
public void load(File file) throws IOException {
FileReader input = null;
Map<Integer,List<BlacklistEntry>> blacklist =
new HashMap<Integer,List<BlacklistEntry>>();
try {
input = new FileReader(file);
BufferedReader buff = new BufferedReader(input);
String line;
List<BlacklistEntry> currentEntries = null;
while ((line = buff.readLine()) != null) {
line = line.trim();
// Blank line
if (line.length() == 0) {
continue;
} else if (line.charAt(0) == ';' || line.charAt(0) == '#') {
continue;
}
if (line.matches("^\\[.*\\]$")) {
String[] items = line.substring(1, line.length() - 1).split(",");
currentEntries = new ArrayList<BlacklistEntry>();
for (String item : items) {
int id = 0;
try {
id = Integer.parseInt(item.trim());
} catch (NumberFormatException e) {
id = etc.getDataSource().getItem(item.trim());
if (id == 0) {
logger.log(Level.WARNING, "WorldGuard: Unknown block name: "
+ item);
break;
}
}
BlacklistEntry entry = new BlacklistEntry(this);
if (blacklist.containsKey(id)) {
blacklist.get(id).add(entry);
} else {
List<BlacklistEntry> entries = new ArrayList<BlacklistEntry>();
entries.add(entry);
blacklist.put(id, entries);
}
currentEntries.add(entry);
}
} else if (currentEntries != null) {
String[] parts = line.split("=");
if (parts.length == 1) {
logger.log(Level.WARNING, "Found option with no value "
+ file.getName() + " for '" + line + "'");
continue;
}
boolean unknownOption = false;
for (BlacklistEntry entry : currentEntries) {
if (parts[0].equalsIgnoreCase("ignore-groups")) {
entry.setIgnoreGroups(parts[1].split(","));
} else if (parts[0].equalsIgnoreCase("on-destroy")) {
entry.setDestroyActions(parts[1].split(","));
} else if (parts[0].equalsIgnoreCase("on-left")
|| parts[0].equalsIgnoreCase("on-destroy-with")) {
entry.setDestroyWithActions(parts[1].split(","));
} else if (parts[0].equalsIgnoreCase("on-right")
|| parts[0].equalsIgnoreCase("on-create")) {
entry.setCreateActions(parts[1].split(","));
} else if (parts[0].equalsIgnoreCase("on-right-on")
|| parts[0].equalsIgnoreCase("on-use")) {
entry.setUseActions(parts[1].split(","));
} else if (parts[0].equalsIgnoreCase("on-drop")) {
entry.setDropActions(parts[1].split(","));
} else {
unknownOption = true;
}
}
if (unknownOption) {
logger.log(Level.WARNING, "Unknown option '" + parts[0]
+ "' in " + file.getName() + " for '" + line + "'");
}
} else {
logger.log(Level.WARNING, "Found option with no heading "
+ file.getName() + " for '" + line + "'");
}
}
this.blacklist = blacklist;
} finally {
try {
if (input != null) {
input.close();
}
} catch (IOException e2) {
}
}
}
}

View File

@ -32,12 +32,12 @@ public class BlacklistEntry {
/**
* Used to prevent spamming.
*/
private static Map<String,Integer> lastAffected =
new HashMap<String,Integer>();
private static Map<String,BlacklistTrackedEvent> lastAffected =
new HashMap<String,BlacklistTrackedEvent>();
/**
* Logger.
* Parent blacklist entry.
*/
private static final Logger logger = Logger.getLogger("WorldGuard.Blacklist");
private Blacklist blacklist;
/**
* List of groups to not affect.
*/
@ -49,15 +49,28 @@ public class BlacklistEntry {
/**
* List of actions to perform on left click.
*/
private String[] leftClickActions;
private String[] destroyWithActions;
/**
* List of actions to perform on right click.
*/
private String[] rightClickActions;
private String[] createActions;
/**
* List of actions to perform on right click upon.
*/
private String[] rightClickOnActions;
private String[] useActions;
/**
* List of actions to perform on drop.
*/
private String[] dropActions;
/**
* Construct the object.
*
* @param blacklist
*/
public BlacklistEntry(Blacklist blacklist) {
this.blacklist = blacklist;
}
/**
* @return the ignoreGroups
@ -78,59 +91,73 @@ public class BlacklistEntry {
}
/**
* @return the destroyActions
* @return
*/
public String[] getDestroyActions() {
return destroyActions;
}
/**
* @param destroyActions the destroyActions to set
* @param actions
*/
public void setDestroyActions(String[] destroyActions) {
this.destroyActions = destroyActions;
}
/**
* @return the leftClickActions
*/
public String[] getLeftClickActions() {
return leftClickActions;
}
/**
* @param leftClickActions the leftClickActions to set
*/
public void setLeftClickActions(String[] leftClickActions) {
this.leftClickActions = leftClickActions;
}
/**
* @return the rightClickActions
*/
public String[] getRightClickActions() {
return rightClickActions;
}
/**
* @param rightClickActions the rightClickActions to set
*/
public void setRightClickActions(String[] rightClickActions) {
this.rightClickActions = rightClickActions;
public void setDestroyActions(String[] actions) {
this.destroyActions = actions;
}
/**
* @return
*/
public String[] getRightClickOnActions() {
return rightClickOnActions;
public String[] getDestroyWithActions() {
return destroyWithActions;
}
/**
* @param action
*/
public void setDestroyWithActions(String[] actions) {
this.destroyWithActions = actions;
}
/**
* @return the rightClickActions
*/
public String[] getCreateActions() {
return createActions;
}
/**
* @param actions
*/
public void setRightClickOnActions(String[] actions) {
this.rightClickOnActions = actions;
public void setCreateActions(String[] actions) {
this.createActions = actions;
}
/**
* @return
*/
public String[] getUseActions() {
return useActions;
}
/**
* @param actions
*/
public void setUseActions(String[] actions) {
this.useActions = actions;
}
/**
* @return
*/
public String[] getDropActions() {
return dropActions;
}
/**
* @param actions
*/
public void setDropActions(String[] actions) {
this.dropActions = actions;
}
/**
@ -159,19 +186,25 @@ public class BlacklistEntry {
*/
public void notifyAdmins(String str) {
for (Player player : etc.getServer().getPlayerList()) {
if (player.canUseCommand("/wprotectalerts")) {
if (player.canUseCommand("/wprotectalerts")
|| player.canUseCommand("/worldguardnotify")) {
player.sendMessage(Colors.LightPurple + "WorldGuard: " + str);
}
}
}
/**
* Log a message.
* Ban a player.
*
* @param message
* @param player
* @param msg
*/
public void log(String message) {
logger.log(Level.INFO, message);
public void banPlayer(Player player, String msg) {
etc.getServer().ban(player.getName());
etc.getLoader().callHook(PluginLoader.Hook.BAN, new Object[]{
player.getUser(), player.getUser(), msg
});
player.kick(msg);
}
/**
@ -182,13 +215,32 @@ public class BlacklistEntry {
* @param player
* @return
*/
public boolean onDestroy(Block block, Player player) {
public boolean onDestroy(final Block block, final Player player) {
if (destroyActions == null) {
return true;
}
boolean ret = process(block.getType(), player, destroyActions);
lastAffected.put(player.getName(), block.getType());
return ret;
final BlacklistEntry entry = this;
ActionHandler handler = new ActionHandler() {
public void log(String itemName) {
blacklist.getLogger().logDestroyAttempt(player, block);
}
public void kick(String itemName) {
player.kick("You are not allowed to destroy " + itemName);
}
public void ban(String itemName) {
entry.banPlayer(player, "Banned: You are not allowed to destroy " + itemName);
}
public void notifyAdmins(String itemName) {
entry.notifyAdmins(player.getName() + " tried to destroy " + itemName + ".");
}
public void tell(String itemName) {
player.sendMessage(Colors.Yellow + "You are not allowed to destroy " + itemName + ".");
}
};
return process(block.getType(), player, destroyActions, handler);
}
/**
@ -198,13 +250,32 @@ public class BlacklistEntry {
* @param player
* @return
*/
public boolean onLeftClick(int item, Player player) {
if (leftClickActions == null) {
public boolean onDestroyWith(final int item, final Player player) {
if (destroyWithActions == null) {
return true;
}
boolean ret = process(item, player, leftClickActions);
lastAffected.put(player.getName(), item);
return ret;
final BlacklistEntry entry = this;
ActionHandler handler = new ActionHandler() {
public void log(String itemName) {
blacklist.getLogger().logDestroyWithAttempt(player, item);
}
public void kick(String itemName) {
player.kick("You can't destroy with " + itemName);
}
public void ban(String itemName) {
entry.banPlayer(player, "Banned: You can't destroy with " + itemName);
}
public void notifyAdmins(String itemName) {
entry.notifyAdmins(player.getName() + " tried to destroyed with " + itemName + ".");
}
public void tell(String itemName) {
player.sendMessage(Colors.Yellow + "You can't destroy with " + itemName + ".");
}
};
return process(item, player, destroyWithActions, handler);
}
/**
@ -214,13 +285,32 @@ public class BlacklistEntry {
* @param player
* @return
*/
public boolean onRightClick(int item, Player player) {
if (rightClickActions == null) {
public boolean onCreate(final int item, final Player player) {
if (createActions == null) {
return true;
}
boolean ret = process(item, player, rightClickActions);
lastAffected.put(player.getName(), item);
return ret;
final BlacklistEntry entry = this;
ActionHandler handler = new ActionHandler() {
public void log(String itemName) {
blacklist.getLogger().logCreateAttempt(player, item);
}
public void kick(String itemName) {
player.kick("You can't create " + itemName);
}
public void ban(String itemName) {
entry.banPlayer(player, "Banned: You can't create " + itemName);
}
public void notifyAdmins(String itemName) {
entry.notifyAdmins(player.getName() + " tried to create " + itemName + ".");
}
public void tell(String itemName) {
player.sendMessage(Colors.Yellow + "You can't create " + itemName + ".");
}
};
return process(item, player, createActions, handler);
}
/**
@ -230,13 +320,95 @@ public class BlacklistEntry {
* @param player
* @return
*/
public boolean onRightClickOn(Block block, Player player) {
if (rightClickOnActions == null) {
public boolean onUse(final Block block, final Player player) {
if (useActions == null) {
return true;
}
boolean ret = process(block.getType(), player, rightClickOnActions);
lastAffected.put(player.getName(), block.getType());
return ret;
final BlacklistEntry entry = this;
ActionHandler handler = new ActionHandler() {
public void log(String itemName) {
blacklist.getLogger().logUseAttempt(player, block);
}
public void kick(String itemName) {
player.kick("You can't use " + itemName);
}
public void ban(String itemName) {
entry.banPlayer(player, "Banned: You can't use " + itemName);
}
public void notifyAdmins(String itemName) {
entry.notifyAdmins(player.getName() + " tried to use " + itemName + ".");
}
public void tell(String itemName) {
player.sendMessage(Colors.Yellow + "You're not allowed to use " + itemName + ".");
}
};
return process(block.getType(), player, useActions, handler);
}
/**
* Called on right click upon. Returns true to let the action pass through.
*
* @param item
* @param player
* @return
*/
public boolean onSilentUse(final Block block, final Player player) {
if (useActions == null) {
return true;
}
ActionHandler handler = new ActionHandler() {
public void log(String itemName) {
}
public void kick(String itemName) {
}
public void ban(String itemName) {
}
public void notifyAdmins(String itemName) {
}
public void tell(String itemName) {
}
};
return process(block.getType(), player, useActions, handler);
}
/**
* Called on item drop. Returns true to let the action pass through.
*
* @param item
* @param player
* @return
*/
public boolean onDrop(final int item, final Player player) {
if (dropActions == null) {
return true;
}
final BlacklistEntry entry = this;
ActionHandler handler = new ActionHandler() {
public void log(String itemName) {
blacklist.getLogger().logDropAttempt(player, item);
}
public void kick(String itemName) {
player.kick("You can't drop " + itemName);
}
public void ban(String itemName) {
entry.banPlayer(player, "Banned: You can't drop " + itemName);
}
public void notifyAdmins(String itemName) {
entry.notifyAdmins(player.getName() + " tried to drop " + itemName + ".");
}
public void tell(String itemName) {
player.sendMessage(Colors.Yellow + "You're not allowed to drop " + itemName + ".");
}
};
return process(item, player, dropActions, handler);
}
/**
@ -247,14 +419,27 @@ public class BlacklistEntry {
* @param actions
* @return
*/
private boolean process(int id, Player player, String[] actions) {
private boolean process(int id, Player player, String[] actions, ActionHandler handler) {
if (shouldIgnore(player)) {
return true;
}
String name = player.getName();
boolean repeating = lastAffected.containsKey(name)
&& lastAffected.get(name) == id;
long now = System.currentTimeMillis();
boolean repeating = false;
// Check to see whether this event is being repeated
BlacklistTrackedEvent tracked = lastAffected.get(name);
if (tracked != null) {
if (tracked.getId() == id && tracked.getTime() > now - 3000) {
repeating = true;
} else {
tracked.setTime(now);
tracked.setId(id);
}
} else {
lastAffected.put(name, new BlacklistTrackedEvent(id, now));
}
boolean ret = true;
@ -262,18 +447,16 @@ public class BlacklistEntry {
if (action.equalsIgnoreCase("deny")) {
ret = false;
} else if (action.equalsIgnoreCase("kick")) {
player.kick("Performed disallowed action with "
+ etc.getDataSource().getItem(id) + ".");
handler.kick(etc.getDataSource().getItem(id));
} else if (action.equalsIgnoreCase("ban")) {
handler.ban(etc.getDataSource().getItem(id));
} else if (!repeating) {
if (action.equalsIgnoreCase("notify")) {
notifyAdmins(player.getName() + " on destroy: "
+ etc.getDataSource().getItem(id));
handler.notifyAdmins(etc.getDataSource().getItem(id));
} else if (action.equalsIgnoreCase("log")) {
log(player.getName() + " on destroy: "
+ etc.getDataSource().getItem(id));
handler.log(etc.getDataSource().getItem(id));
} else if (!repeating && action.equalsIgnoreCase("tell")) {
player.sendMessage("Can't do that with "
+ etc.getDataSource().getItem(id) + ".");
handler.tell(etc.getDataSource().getItem(id));
}
}
}
@ -296,6 +479,17 @@ public class BlacklistEntry {
* @param player
*/
public static void forgetAllPlayers() {
lastAffected = new HashMap<String,Integer>();
lastAffected.clear();
}
/**
* Gets called for actions.
*/
private static interface ActionHandler {
public void log(String itemName);
public void kick(String itemName);
public void ban(String itemName);
public void notifyAdmins(String itemName);
public void tell(String itemName);
}
}

129
src/BlacklistLogger.java Normal file
View File

@ -0,0 +1,129 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.util.Set;
import java.util.HashSet;
/**
*
* @author sk89q
*/
public class BlacklistLogger implements BlacklistLoggerHandler {
/**
* List of logger handlers.
*/
private Set<BlacklistLoggerHandler> handlers
= new HashSet<BlacklistLoggerHandler>();
/**
* Add a handler.
*
* @param handler
*/
public void addHandler(BlacklistLoggerHandler handler) {
handlers.add(handler);
}
/**
* Add a handler.
*
* @param handler
*/
public void removeHandler(BlacklistLoggerHandler handler) {
handlers.remove(handler);
}
/**
* Add a handler.
*
* @param handler
*/
public void clearHandlers() {
handlers.clear();
}
/**
* Log a block destroy attempt.
*
* @param player
* @param block
*/
public void logDestroyAttempt(Player player, Block block) {
for (BlacklistLoggerHandler handler : handlers) {
handler.logDestroyAttempt(player, block);
}
}
/**
* Log a right click on attempt.
*
* @param player
* @param block
*/
public void logUseAttempt(Player player, Block block) {
for (BlacklistLoggerHandler handler : handlers) {
handler.logUseAttempt(player, block);
}
}
/**
* Right a left click attempt.
*
* @param player
* @param item
*/
public void logDestroyWithAttempt(Player player, int item) {
for (BlacklistLoggerHandler handler : handlers) {
handler.logDestroyWithAttempt(player, item);
}
}
/**
* Log a right click attempt.
*
* @param player
* @param item
*/
public void logCreateAttempt(Player player, int item) {
for (BlacklistLoggerHandler handler : handlers) {
handler.logCreateAttempt(player, item);
}
}
/**
* Log a right click attempt.
*
* @param player
* @param item
*/
public void logDropAttempt(Player player, int item) {
for (BlacklistLoggerHandler handler : handlers) {
handler.logDropAttempt(player, item);
}
}
/**
* Close the connection.
*/
public void close() {
for (BlacklistLoggerHandler handler : handlers) {
handler.close();
}
}
}

View File

@ -0,0 +1,65 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Interface for loggers for the blacklist.
*
* @author sk89q
*/
public interface BlacklistLoggerHandler {
/**
* Log a block destroy attempt.
*
* @param player
* @param block
*/
public void logDestroyAttempt(Player player, Block block);
/**
* Log a right click on attempt.
*
* @param player
* @param block
*/
public void logUseAttempt(Player player, Block block);
/**
* Right a left click attempt.
*
* @param player
* @param item
*/
public void logDestroyWithAttempt(Player player, int item);
/**
* Log a right click attempt.
*
* @param player
* @param item
*/
public void logCreateAttempt(Player player, int item);
/**
* Log a drop attempt.
*
* @param player
* @param item
*/
public void logDropAttempt(Player player, int item);
/**
* Close the logger.
*/
public void close();
}

View File

@ -0,0 +1,66 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
*
* @author sk89q
*/
public class BlacklistTrackedEvent {
private int id;
private long time;
/**
* Construct the object.
*
* @param id
* @param time
*/
public BlacklistTrackedEvent(int id, long time) {
this.id = id;
this.time = time;
}
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* @return the time
*/
public long getTime() {
return time;
}
/**
* @param time the time to set
*/
public void setTime(long time) {
this.time = time;
}
}

View File

@ -0,0 +1,102 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.util.logging.Logger;
import java.util.logging.Level;
/**
*
* @author sk89q
*/
public class ConsoleLoggerHandler implements BlacklistLoggerHandler {
/**
* Logger.
*/
private static final Logger logger = Logger.getLogger("Minecraft.WorldGuard");
/**
* Log a block destroy attempt.
*
* @param player
* @param block
*/
public void logDestroyAttempt(Player player, Block block) {
logger.log(Level.INFO, "WorldGuard: " + player.getName()
+ " tried to destroy " + getFriendlyItemName(block.getType()));
}
/**
* Log a right click on attempt.
*
* @param player
* @param block
*/
public void logUseAttempt(Player player, Block block) {
logger.log(Level.INFO, "WorldGuard: " + player.getName()
+ " tried to use " + getFriendlyItemName(block.getType()));
}
/**
* Log an attempt to destroy with an item.
*
* @param player
* @param item
*/
public void logDestroyWithAttempt(Player player, int item) {
logger.log(Level.INFO, "WorldGuard: " + player.getName()
+ " tried to destroy with " + getFriendlyItemName(item));
}
/**
* Log a block creation attempt.
*
* @param player
* @param item
*/
public void logCreateAttempt(Player player, int item) {
logger.log(Level.INFO, "WorldGuard: " + player.getName()
+ " tried to create " + getFriendlyItemName(item));
}
/**
* Log a drop attempt.
*
* @param player
* @param item
*/
public void logDropAttempt(Player player, int item) {
logger.log(Level.INFO, "WorldGuard: " + player.getName()
+ " tried to drop " + getFriendlyItemName(item));
}
/**
* Get an item's friendly name with its ID.
*
* @param id
*/
private static String getFriendlyItemName(int id) {
return etc.getDataSource().getItem(id) + " (#" + id + ")";
}
/**
* Close the connection.
*/
public void close() {
}
}

View File

@ -0,0 +1,186 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.util.logging.Logger;
import java.util.logging.Level;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.PreparedStatement;
/**
*
* @author sk89q
*/
public class DatabaseLoggerHandler implements BlacklistLoggerHandler {
/**
* Logger.
*/
private static final Logger logger = Logger.getLogger("Minecraft.WorldGuard");
/**
* DSN.
*/
private String dsn;
/**
* Username.
*/
private String user;
/**
* Password.
*/
private String pass;
/**
* Table.
*/
private String table;
/**
* Database connection.
*/
private Connection conn;
/**
* Construct the object.
*
* @param dsn
* @param user
* @param pass
*/
public DatabaseLoggerHandler(String dsn, String user, String pass, String table) {
this.dsn = dsn;
this.user = user;
this.pass = pass;
this.table = table;
}
/**
* Gets the database connection.
*
* @return
* @throws SQLException
*/
private Connection getConnection() throws SQLException {
if (conn == null || conn.isClosed()) {
conn = DriverManager.getConnection(dsn, user, pass);
}
return conn;
}
/**
* Log an event to the database.
*
* @param event
* @param name
* @param x
* @param y
* @param z
* @param item
*/
private void logEvent(String event, String name, int x, int y, int z, int item) {
try {
Connection conn = getConnection();
PreparedStatement stmt = conn.prepareStatement(
"INSERT INTO " + table
+ "(event, player, x, y, z, item, time) VALUES "
+ "(?, ?, ?, ?, ?, ?, ?)");
stmt.setString(1, event);
stmt.setString(2, name);
stmt.setInt(3, x);
stmt.setInt(4, y);
stmt.setInt(5, z);
stmt.setInt(6, item);
stmt.setInt(7, (int)(System.currentTimeMillis() / 1000));
stmt.executeUpdate();
} catch (SQLException e) {
logger.log(Level.SEVERE, "Failed to log blacklist event to database: "
+ e.getMessage());
}
}
/**
* Log a block destroy attempt.
*
* @param player
* @param block
*/
public void logDestroyAttempt(Player player, Block block) {
logEvent("DESTROY", player.getName(),
block.getX(), block.getY(), block.getZ(), block.getType());
}
/**
* Log a right click on attempt.
*
* @param player
* @param block
*/
public void logUseAttempt(Player player, Block block) {
logEvent("USE", player.getName(),
block.getX(), block.getY(), block.getZ(), block.getType());
}
/**
* Right a left click attempt.
*
* @param player
* @param item
*/
public void logDestroyWithAttempt(Player player, int item) {
logEvent("DESTROY_WITH", player.getName(),
(int)Math.floor(player.getX()), (int)Math.floor(player.getY()),
(int)Math.floor(player.getZ()), item);
}
/**
* Log a right click attempt.
*
* @param player
* @param item
*/
public void logCreateAttempt(Player player, int item) {
logEvent("CREATE", player.getName(),
(int)Math.floor(player.getX()), (int)Math.floor(player.getY()),
(int)Math.floor(player.getZ()), item);
}
/**
* Log a drop attempt.
*
* @param player
* @param item
*/
public void logDropAttempt(Player player, int item) {
logEvent("DROP", player.getName(),
(int)Math.floor(player.getX()), (int)Math.floor(player.getY()),
(int)Math.floor(player.getZ()), item);
}
/**
* Close the connection.
*/
public void close() {
try {
if (conn != null && !conn.isClosed()) {
conn.close();
}
} catch (SQLException e) {
}
}
}

280
src/FileLoggerHandler.java Normal file
View File

@ -0,0 +1,280 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.util.logging.Logger;
import java.util.logging.Level;
import java.io.*;
import java.util.regex.*;
import java.util.Map;
import java.util.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TreeMap;
import java.util.Iterator;
import java.text.SimpleDateFormat;
/**
*
* @author sk89q
*/
public class FileLoggerHandler implements BlacklistLoggerHandler {
/**
* Logger.
*/
private static final Logger logger = Logger.getLogger("Minecraft.WorldGuard");
/**
* Regex for patterns in the path.
*/
private static Pattern pattern = Pattern.compile("%.");
/**
* Date format.
*/
private static SimpleDateFormat dateFormat =
new SimpleDateFormat("yyyyy-MM-dd HH:mm:ss");
/**
* Number of files to keep open at a time.
*/
private int cacheSize = 10;
/**
* Path pattern.
*/
private String pathPattern;
/**
* Cache of writers.
*/
private TreeMap<String,FileLoggerWriter> writers =
new TreeMap<String,FileLoggerWriter>();
/**
* Construct the object.
*
* @param pathPattern
*/
public FileLoggerHandler(String pathPattern) {
this.pathPattern = pathPattern;
}
/**
* Construct the object.
*
* @param pathPattern
* @param cacheSize
*/
public FileLoggerHandler(String pathPattern, int cacheSize) {
if (cacheSize < 1) {
throw new IllegalArgumentException("Cache size cannot be less than 1");
}
this.pathPattern = pathPattern;
this.cacheSize = cacheSize;
}
/**
* Build the path.
*
* @return
*/
private String buildPath(String playerName) {
GregorianCalendar calendar = new GregorianCalendar();
Pattern p = Pattern.compile("%.");
Matcher m = p.matcher(pathPattern);
StringBuffer buffer = new StringBuffer();
// Pattern replacements
while (m.find()) {
String group = m.group();
String rep = "?";
if (group.matches("%%")) {
rep = "%";
} else if (group.matches("%u")) {
rep = playerName.toLowerCase().replaceAll("[^A-Za-z0-9_]", "_");
if (rep.length() > 32) { // Actual max length is 16
rep = rep.substring(0, 32);
}
// Date and time
} else if (group.matches("%Y")) {
rep = String.valueOf(calendar.get(Calendar.YEAR));
} else if (group.matches("%m")) {
rep = String.format("%02d", calendar.get(Calendar.MONTH));
} else if (group.matches("%d")) {
rep = String.format("%02d", calendar.get(Calendar.DAY_OF_MONTH));
} else if (group.matches("%W")) {
rep = String.format("%02d", calendar.get(Calendar.WEEK_OF_YEAR));
} else if (group.matches("%H")) {
rep = String.format("%02d", calendar.get(Calendar.HOUR_OF_DAY));
} else if (group.matches("%h")) {
rep = String.format("%02d", calendar.get(Calendar.HOUR));
} else if (group.matches("%i")) {
rep = String.format("%02d", calendar.get(Calendar.MINUTE));
} else if (group.matches("%s")) {
rep = String.format("%02d", calendar.get(Calendar.SECOND));
}
m.appendReplacement(buffer, rep);
}
m.appendTail(buffer);
return buffer.toString();
}
/**
* Log a message.
*
* @param player
* @param message
*/
private void log(Player player, String message) {
String path = buildPath(player.getName());
try {
String date = dateFormat.format(new Date());
String line = "[" + date + "] " + player.getName() + ": " + message + "\r\n";
FileLoggerWriter writer = writers.get(path);
// Writer already exists!
if (writer != null) {
try {
BufferedWriter out = writer.getWriter();
out.write(line);
out.flush();
writer.updateLastUse();
return;
} catch (IOException e) {
// Failed initial rewrite... let's re-open
}
}
// Make parent directory
File file = new File(path);
File parent = file.getParentFile();
if (parent != null && !parent.exists()) {
parent.mkdirs();
}
FileWriter stream = new FileWriter(path, true);
BufferedWriter out = new BufferedWriter(stream);
out.write(line);
out.flush();
writer = new FileLoggerWriter(path, out);
writers.put(path, writer);
// Check to make sure our cache doesn't get too big!
if (writers.size() > cacheSize) {
Iterator<Map.Entry<String,FileLoggerWriter>> it =
writers.entrySet().iterator();
// Remove some entries
for (; it.hasNext(); ) {
Map.Entry<String,FileLoggerWriter> entry = it.next();
try {
entry.getValue().getWriter().close();
} catch (IOException e) {
}
it.remove();
// Trimmed enough
if (writers.size() <= cacheSize) {
break;
}
}
}
} catch (IOException e) {
logger.log(Level.WARNING, "Failed to log blacklist event to '"
+ path + "': " + e.getMessage());
}
}
/**
* Log a block destroy attempt.
*
* @param player
* @param block
*/
public void logDestroyAttempt(Player player, Block block) {
log(player, "Tried to destroy " + getFriendlyItemName(block.getType()));
}
/**
* Log a right click on attempt.
*
* @param player
* @param block
*/
public void logUseAttempt(Player player, Block block) {
log(player, "Tried to use " + getFriendlyItemName(block.getType()));
}
/**
* Log an attempt to destroy with an item.
*
* @param player
* @param item
*/
public void logDestroyWithAttempt(Player player, int item) {
log(player, "Tried to destroy with " + getFriendlyItemName(item));
}
/**
* Log a block creation attempt.
*
* @param player
* @param item
*/
public void logCreateAttempt(Player player, int item) {
log(player, "Tried to create " + getFriendlyItemName(item));
}
/**
* Log a drop attempt.
*
* @param player
* @param item
*/
public void logDropAttempt(Player player, int item) {
log(player, "Tried to drop " + getFriendlyItemName(item));
}
/**
* Get an item's friendly name with its ID.
*
* @param id
*/
private static String getFriendlyItemName(int id) {
return etc.getDataSource().getItem(id) + " (#" + id + ")";
}
/**
* Close handles.
*/
public void close() {
for (Map.Entry<String,FileLoggerWriter> entry : writers.entrySet()) {
try {
entry.getValue().getWriter().close();
} catch (IOException e) {
}
}
writers.clear();
}
}

98
src/FileLoggerWriter.java Normal file
View File

@ -0,0 +1,98 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.io.*;
/**
*
* @author sk89q
*/
public class FileLoggerWriter implements Comparable<FileLoggerWriter> {
/**
* Path.
*/
public String path;
/**
* Writer.
*/
private BufferedWriter writer;
/**
* Last use.
*/
private long lastUse;
/**
* Construct the object.
*
* @param writer
*/
public FileLoggerWriter(String path, BufferedWriter writer) {
this.path = path;
this.writer = writer;
lastUse = System.currentTimeMillis();
}
/**
* File path.
*
* @return
*/
public String getPath() {
return path;
}
/**
* @return the writer
*/
public BufferedWriter getWriter() {
return writer;
}
/**
* @return the lastUse
*/
public long getLastUse() {
return lastUse;
}
/**
* Update last use time.
*
* @return
*/
public void updateLastUse() {
lastUse = System.currentTimeMillis();
}
/**
* Comparison function.
*
* @param other
* @return
*/
public int compareTo(FileLoggerWriter other) {
if (lastUse > other.lastUse) {
return 1;
} else if (lastUse < other.lastUse) {
return -1;
} else {
return 0;
}
}
}

View File

@ -69,6 +69,10 @@ public class WorldGuard extends Plugin {
PluginListener.Priority.HIGH);
loader.addListener(PluginLoader.Hook.ITEM_DROP , listener, this,
PluginListener.Priority.HIGH);
loader.addListener(PluginLoader.Hook.COMPLEX_BLOCK_CHANGE, listener, this,
PluginListener.Priority.HIGH);
loader.addListener(PluginLoader.Hook.COMPLEX_BLOCK_SEND, listener, this,
PluginListener.Priority.HIGH);
}
/**

View File

@ -25,10 +25,6 @@ import java.util.logging.Handler;
import java.util.logging.ConsoleHandler;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Random;
import java.io.*;
@ -79,7 +75,7 @@ public class WorldGuardListener extends PluginListener {
private Set<Integer> allowedLavaSpreadOver;
private Set<Integer> itemDropBlacklist;
private boolean classicWater;
private Map<Integer,BlacklistEntry> blacklist;
private Blacklist blacklist;
/**
* Construct the listener.
@ -127,6 +123,7 @@ public class WorldGuardListener extends PluginListener {
public void loadConfiguration() {
properties.load();
// Load basic options
enforceOneSession = properties.getBoolean("enforce-single-session", true);
blockCreepers = properties.getBoolean("block-creepers", false);
blockTNT = properties.getBoolean("block-tnt", false);
@ -140,8 +137,51 @@ public class WorldGuardListener extends PluginListener {
simulateSponge = properties.getBoolean("simulate-sponge", false);
blockLagFix = properties.getBoolean("block-lag-fix", false);
// Console log configuration
boolean logConsole = properties.getBoolean("log-console", true);
// Database log configuration
boolean logDatabase = properties.getBoolean("log-database", false);
String dsn = properties.getString("log-database-dsn", "jdbc:mysql://localhost:3306/minecraft");
String user = properties.getString("log-database-user", "root");
String pass = properties.getString("log-database-pass", "");
String table = properties.getString("log-database-table", "blacklist_events");
// File log configuration
boolean logFile = properties.getBoolean("log-file", false);
String logFilePattern = properties.getString("log-file-path", "worldguard/logs/%Y-%m-%d.log");
int logFileCacheSize = Math.max(1, properties.getInt("log-file-open-files", 10));
// Load the blacklist
try {
blacklist = loadBlacklist(new File("worldguard-blacklist.txt"));
// First load the blacklist data from worldguard-blacklist.txt
Blacklist blacklist = new Blacklist();
blacklist.load(new File("worldguard-blacklist.txt"));
// If the blacklist is empty, then set the field to null
// and save some resources
if (blacklist.isEmpty()) {
this.blacklist = null;
} else {
this.blacklist = blacklist;
logger.log(Level.INFO, "WorldGuard: Blacklist loaded.");
BlacklistLogger blacklistLogger = blacklist.getLogger();
if (logDatabase) {
blacklistLogger.addHandler(new DatabaseLoggerHandler(dsn, user, pass, table));
}
if (logConsole) {
blacklistLogger.addHandler(new ConsoleLoggerHandler());
}
if (logFile) {
FileLoggerHandler handler =
new FileLoggerHandler(logFilePattern, logFileCacheSize);
blacklistLogger.addHandler(handler);
}
}
} catch (FileNotFoundException e) {
logger.log(Level.WARNING, "WorldGuard blacklist does not exist.");
} catch (IOException e) {
@ -149,34 +189,7 @@ public class WorldGuardListener extends PluginListener {
+ e.getMessage());
}
Logger blacklistLogger = Logger.getLogger("WorldGuard.Blacklist");
blacklistLogger.setUseParentHandlers(false);
for (Handler handler : blacklistLogger.getHandlers()) {
blacklistLogger.removeHandler(handler);
}
// Blacklist log to console
if (properties.getBoolean("blacklist-log-console", true)) {
Handler handler = new ConsoleHandler();
handler.setFormatter(new ConsoleLogFormat());
blacklistLogger.addHandler(handler);
}
// Blacklist log file
String logFile = properties.getString("blacklist-log-file", "").trim();
int limit = properties.getInt("blacklist-log-file-limit", 1024 * 1024 * 5);
int count = properties.getInt("blacklist-log-file-count", 10);
if (logFile.length() > 0) {
try {
Handler handler = new FileHandler(logFile, limit, count, true);
handler.setFormatter(new SimpleLogFormat());
blacklistLogger.addHandler(handler);
} catch (IOException e) {
logger.log(Level.WARNING, "Could not open blacklist log file: "
+ e.getMessage());
}
}
// Print an overview of settings
logger.log(Level.INFO, enforceOneSession ? "WorldGuard: Single session is enforced."
: "WorldGuard: Single session is NOT ENFORCED.");
logger.log(Level.INFO, blockTNT ? "WorldGuard: TNT ignition is blocked."
@ -234,6 +247,12 @@ public class WorldGuardListener extends PluginListener {
return true;
}
}
if (blacklist != null) {
if (!blacklist.onDrop(item.getItemId(), player)) {
return true;
}
}
return false;
}
@ -252,32 +271,29 @@ public class WorldGuardListener extends PluginListener {
public boolean onBlockCreate(Player player, Block blockPlaced, Block blockClicked,
int itemInHand) {
if (blacklist != null) {
BlacklistEntry entry = blacklist.get(itemInHand);
if (entry != null) {
if (!entry.onRightClick(itemInHand, player)) {
// Water/lava bucket fix
if (itemInHand == 326 || itemInHand == 327) {
final int x = blockPlaced.getX();
final int y = blockPlaced.getY();
final int z = blockPlaced.getZ();
final int existingID = etc.getServer().getBlockIdAt(x, y, z);
if (!blacklist.onCreate(itemInHand, player)) {
// Water/lava bucket fix
if (itemInHand == 326 || itemInHand == 327) {
final int x = blockPlaced.getX();
final int y = blockPlaced.getY();
final int z = blockPlaced.getZ();
final int existingID = etc.getServer().getBlockIdAt(x, y, z);
// This is REALLY BAD, but there's no other choice
// at the moment that is as reliable
timer.schedule(new TimerTask() {
public void run() {
try {
etc.getServer().setBlockAt(existingID, x, y, z);
} catch (Throwable t) {}
}
}, 200); // Just in case
}
return true;
// This is REALLY BAD, but there's no other choice
// at the moment that is as reliable
timer.schedule(new TimerTask() {
public void run() {
try {
etc.getServer().setBlockAt(existingID, x, y, z);
} catch (Throwable t) {}
}
}, 200); // Just in case
}
return true;
}
if (!entry.onRightClickOn(blockClicked, player)) {
return true;
}
if (!blacklist.onUse(blockClicked, player)) {
return true;
}
}
@ -295,18 +311,12 @@ public class WorldGuardListener extends PluginListener {
int type = block.getType();
if (blacklist != null) {
BlacklistEntry entry = blacklist.get(player.getItemInHand());
if (entry != null) {
if (entry.onLeftClick(player.getItemInHand(), player)) {
return true;
}
if (!blacklist.onDestroyWith(player.getItemInHand(), player)) {
return true;
}
entry = blacklist.get(block.getType());
if (entry != null) {
if (!entry.onDestroy(block, player)) {
return true;
}
if (!blacklist.onDestroy(block, player)) {
return true;
}
}
@ -392,6 +402,90 @@ public class WorldGuardListener extends PluginListener {
return false;
}
/**
* Called when either a sign, chest or furnace is changed.
*
* @param player
* player who changed it
* @param complexBlock
* complex block that changed
* @return true if you want any changes to be reverted
*/
public boolean onComplexBlockChange(Player player, ComplexBlock complexBlock) {
if (blacklist != null) {
if (complexBlock instanceof Chest) {
Block block = new Block(54, complexBlock.getX(),
complexBlock.getY(), complexBlock.getZ());
if (!blacklist.onSilentUse(block, player)) {
return true;
}
} else if (complexBlock instanceof Furnace) {
int id = etc.getServer().getBlockIdAt(complexBlock.getX(),
complexBlock.getY(), complexBlock.getZ());
Block block = new Block(id, complexBlock.getX(),
complexBlock.getY(), complexBlock.getZ());
if (!blacklist.onSilentUse(block, player)) {
return true;
}
} else if (complexBlock instanceof Sign) {
int id = etc.getServer().getBlockIdAt(complexBlock.getX(),
complexBlock.getY(), complexBlock.getZ());
Block block = new Block(id, complexBlock.getX(),
complexBlock.getY(), complexBlock.getZ());
if (!blacklist.onSilentUse(block, player)) {
return true;
}
}
}
return false;
}
/**
* Called when either a sign, chest or furnace is sent to a player
*
* @param player
* player who the block is being sent to
* @param complexBlock
* complex block that's being sent
* @return true if you want the chest, furnace or sign to be empty
*/
public boolean onSendComplexBlock(Player player, ComplexBlock complexBlock) {
if (blacklist != null) {
if (complexBlock instanceof Chest) {
Block block = new Block(54, complexBlock.getX(),
complexBlock.getY(), complexBlock.getZ());
if (!blacklist.onSilentUse(block, player)) {
return true;
}
} else if (complexBlock instanceof Furnace) {
int id = etc.getServer().getBlockIdAt(complexBlock.getX(),
complexBlock.getY(), complexBlock.getZ());
Block block = new Block(id, complexBlock.getX(),
complexBlock.getY(), complexBlock.getZ());
if (!blacklist.onSilentUse(block, player)) {
return true;
}
} else if (complexBlock instanceof Sign) {
int id = etc.getServer().getBlockIdAt(complexBlock.getX(),
complexBlock.getY(), complexBlock.getZ());
Block block = new Block(id, complexBlock.getX(),
complexBlock.getY(), complexBlock.getZ());
if (!blacklist.onSilentUse(block, player)) {
return true;
}
}
}
return false;
}
/*
* Called when either a lava block or a lighter tryes to light something on fire.
* block status depends on the light source:
@ -535,102 +629,4 @@ public class WorldGuardListener extends PluginListener {
plugin.toggleEnabled();
}
}
/**
* Load the blacklist.
*
* @param file
* @return
* @throws IOException
*/
public Map<Integer,BlacklistEntry> loadBlacklist(File file)
throws IOException {
FileReader input = null;
Map<Integer,BlacklistEntry> blacklist = new HashMap<Integer,BlacklistEntry>();
try {
input = new FileReader(file);
BufferedReader buff = new BufferedReader(input);
String line;
List<BlacklistEntry> entries = null;
while ((line = buff.readLine()) != null) {
line = line.trim();
// Blank line
if (line.length() == 0) {
continue;
} else if (line.charAt(0) == ';' || line.charAt(0) == '#') {
continue;
}
if (line.matches("^\\[.*\\]$")) {
String[] items = line.substring(1, line.length() - 1).split(",");
entries = new ArrayList<BlacklistEntry>();
for (String item : items) {
int id = 0;
try {
id = Integer.parseInt(item.trim());
} catch (NumberFormatException e) {
id = etc.getDataSource().getItem(item.trim());
if (id == 0) {
logger.log(Level.WARNING, "WorldGuard: Unknown block name: "
+ item);
break;
}
}
BlacklistEntry entry = new BlacklistEntry();
blacklist.put(id, entry);
entries.add(entry);
}
} else if (entries != null) {
String[] parts = line.split("=");
if (parts.length == 1) {
logger.log(Level.WARNING, "Found option with no value "
+ file.getName() + " for '" + line + "'");
continue;
}
boolean unknownOption = false;
for (BlacklistEntry entry : entries) {
if (parts[0].equalsIgnoreCase("ignore-groups")) {
entry.setIgnoreGroups(parts[1].split(","));
} else if(parts[0].equalsIgnoreCase("on-destroy")) {
entry.setDestroyActions(parts[1].split(","));
} else if(parts[0].equalsIgnoreCase("on-left")) {
entry.setLeftClickActions(parts[1].split(","));
} else if(parts[0].equalsIgnoreCase("on-right")) {
entry.setRightClickActions(parts[1].split(","));
} else if(parts[0].equalsIgnoreCase("on-right-on")) {
entry.setRightClickOnActions(parts[1].split(","));
} else {
unknownOption = true;
}
}
if (unknownOption) {
logger.log(Level.WARNING, "Unknown option '" + parts[0]
+ "' in " + file.getName() + " for '" + line + "'");
}
} else {
logger.log(Level.WARNING, "Found option with no heading "
+ file.getName() + " for '" + line + "'");
}
}
return blacklist.isEmpty() ? null : blacklist;
} finally {
try {
if (input != null) {
input.close();
}
} catch (IOException e2) {
}
}
}
}

View File

@ -3,30 +3,45 @@
# are ignored so you can put your own notes.
#
# Format:
# [item1,item2,itemN]
# [item1,item2]
# option1=options
# event1=action1,action2,actionN
# eventN=action1,action2,actionN
# event1=whatToDo1,whatToDo2,whatToDo3
# event2=whatToDo1,whatToDo2
#
# Events/Options:
# Example to block ore and catch some events:
# [coalore,goldore,ironore]
# on-destroy-with=deny,log,kick
# on-create=deny,tell
#
# Options:
# - ignore-groups (comma-delimited list of groups to not affect)
# - on-destroy (when a block of this type is destroyed)
# - on-left (when this item is held and the player is left clicking)
# - on-right (when this item is held and the player is right clicking)
#
# Actions:
# Events:
# - on-destroy (when a block of this type is being destroyed)
# - on-destroy-with (the item/block held by the user while destroying)
# - on-create (the item/block in the user's inventory is being created)
# - on-use (the block is right clicked)
# - on-drop (the item is being dropped from the player's inventory)
#
# Actions (for events):
# - deny (deny completely)
# - notify (notify admins)
# - log (log to console/file)
# - kick (kick player)
# - log (log to console/file/database)
# - tell (tell a player that that's not allowed)
# - kick (kick player)
# - ban (ban player)
#
# Some examples follow.
# Users with the /worldguardnotify permission will be receive notifications.
#
# Some examples follow. Remember to remove # in front if you want them
# to work for you!
#[lavabucket]
#on-left=deny,log,kick
#on-right=deny,tell
#on-destroy-with=deny,log,kick
#on-create=deny,tell
#[coalore,goldore,ironore]
#on-destroy=notify,deny,log
#[cobblestone]
#on-right=deny,tell,log
#on-create=deny,tell,log