Removed no longer needed workarounds + lots of code formatting

This commit is contained in:
Evenprime 2011-08-09 15:58:05 +02:00
parent 33e9c46716
commit 7e0721da98
48 changed files with 2203 additions and 2311 deletions

View File

@ -3,7 +3,7 @@ name: NoCheat
author: Evenprime author: Evenprime
main: cc.co.evenprime.bukkit.nocheat.NoCheat main: cc.co.evenprime.bukkit.nocheat.NoCheat
version: 1.12 version: 1.12a
softdepend: [ Permissions, CraftIRC ] softdepend: [ Permissions, CraftIRC ]

View File

@ -2,12 +2,12 @@ package cc.co.evenprime.bukkit.nocheat;
public class ConfigurationException extends Exception { public class ConfigurationException extends Exception {
/** /**
* *
*/ */
private static final long serialVersionUID = -457634587532590464L; private static final long serialVersionUID = -457634587532590464L;
public ConfigurationException(String message) { public ConfigurationException(String message) {
super(message); super(message);
} }
} }

View File

@ -42,8 +42,7 @@ public class CustomCommandSender implements CommandSender {
} }
@Override @Override
public PermissionAttachment addAttachment(Plugin plugin, String name, public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) {
boolean value) {
// Whatever it is, I don't care // Whatever it is, I don't care
return null; return null;
} }
@ -55,8 +54,7 @@ public class CustomCommandSender implements CommandSender {
} }
@Override @Override
public PermissionAttachment addAttachment(Plugin plugin, String name, public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) {
boolean value, int ticks) {
// Whatever it is, I don't care // Whatever it is, I don't care
return null; return null;
} }

View File

@ -14,156 +14,154 @@ import cc.co.evenprime.bukkit.nocheat.data.NukeData;
import cc.co.evenprime.bukkit.nocheat.data.PermissionData; import cc.co.evenprime.bukkit.nocheat.data.PermissionData;
import cc.co.evenprime.bukkit.nocheat.data.SpeedhackData; import cc.co.evenprime.bukkit.nocheat.data.SpeedhackData;
public class DataManager { public class DataManager {
// Store data between Events // Store data between Events
private final Map<Player, NoCheatData> playerData = new HashMap<Player, NoCheatData>(); private final Map<Player, NoCheatData> playerData = new HashMap<Player, NoCheatData>();
public DataManager() { } public DataManager() {}
/** /**
* Go through the playerData HashMap and remove players that are no longer online * Go through the playerData HashMap and remove players that are no longer
* from the map. This should be called in long, regular intervals (e.g. every 10 minutes) * online
* to keep the memory footprint of the plugin low * from the map. This should be called in long, regular intervals (e.g.
*/ * every 10 minutes)
public void cleanPlayerDataCollection() { * to keep the memory footprint of the plugin low
synchronized(playerData) { */
Iterator<Map.Entry<Player, NoCheatData>> it = playerData.entrySet().iterator(); public void cleanPlayerDataCollection() {
while (it.hasNext()) { synchronized(playerData) {
Map.Entry<Player, NoCheatData> pairs = (Map.Entry<Player, NoCheatData>)it.next(); Iterator<Map.Entry<Player, NoCheatData>> it = playerData.entrySet().iterator();
if(!pairs.getKey().isOnline()) { while(it.hasNext()) {
// Cancel all referenced tasks before removing the entry Map.Entry<Player, NoCheatData> pairs = (Map.Entry<Player, NoCheatData>) it.next();
cancelTasks(pairs.getValue()); if(!pairs.getKey().isOnline()) {
// Cancel all referenced tasks before removing the entry
cancelTasks(pairs.getValue());
it.remove(); it.remove();
} }
} }
} }
} }
/** /**
* Main access to data that needs to be stored between different events. * Main access to data that needs to be stored between different events.
* Always returns a NoCheatData object, because if there isn't one * Always returns a NoCheatData object, because if there isn't one
* for the specified player, one will be created. * for the specified player, one will be created.
* *
* @param p * @param p
* @return * @return
*/ */
public NoCheatData getPlayerData(Player p) { private NoCheatData getPlayerData(final Player p) {
NoCheatData data = playerData.get(p); NoCheatData data = playerData.get(p);
if(data == null) { if(data == null) {
synchronized(playerData) { synchronized(playerData) {
// If we have no data for the player, create some // If we have no data for the player, create some
data = new NoCheatData(); data = new NoCheatData();
playerData.put(p, data); playerData.put(p, data);
} }
} }
return data; return data;
} }
public AirbuildData getAirbuildData(Player p) {
NoCheatData data = getPlayerData(p); public AirbuildData getAirbuildData(Player p) {
if(data.airbuild == null) { NoCheatData data = getPlayerData(p);
data.airbuild = new AirbuildData();
}
return data.airbuild; if(data.airbuild == null) {
} data.airbuild = new AirbuildData();
}
public MovingData getMovingData(final Player p) {
final NoCheatData data = getPlayerData(p); return data.airbuild;
}
if(data.moving == null) { public MovingData getMovingData(final Player p) {
data.moving = new MovingData();
data.moving.teleportedTo = p.getLocation();
}
return data.moving; final NoCheatData data = getPlayerData(p);
}
public NukeData getNukeData(Player p) {
NoCheatData data = getPlayerData(p); if(data.moving == null) {
data.moving = new MovingData();
}
if(data.nuke == null) { return data.moving;
data.nuke = new NukeData(); }
}
return data.nuke; public NukeData getNukeData(Player p) {
}
public PermissionData getPermissionData(Player p) {
NoCheatData data = getPlayerData(p); NoCheatData data = getPlayerData(p);
if(data.permission == null) { if(data.nuke == null) {
data.permission = new PermissionData(); data.nuke = new NukeData();
} }
return data.permission; return data.nuke;
} }
public SpeedhackData getSpeedhackData(Player p) {
NoCheatData data = getPlayerData(p); public PermissionData getPermissionData(Player p) {
if(data.speedhack == null) { NoCheatData data = getPlayerData(p);
data.speedhack = new SpeedhackData();
}
return data.speedhack; if(data.permission == null) {
} data.permission = new PermissionData();
}
return data.permission;
}
public SpeedhackData getSpeedhackData(Player p) {
NoCheatData data = getPlayerData(p);
if(data.speedhack == null) {
data.speedhack = new SpeedhackData();
}
return data.speedhack;
}
/**
* Go through the playerData HashMap and remove players that are no longer
* online
* from the map. This should be called in long, regular intervals (e.g.
* every 10 minutes)
* to keep the memory footprint of the plugin low
*/
public void cancelPlayerDataTasks() {
synchronized(playerData) {
Iterator<Map.Entry<Player, NoCheatData>> it = playerData.entrySet().iterator();
while(it.hasNext()) {
cancelTasks(it.next().getValue());
}
}
}
private void cancelTasks(NoCheatData data) {
/**
* Go through the playerData HashMap and remove players that are no longer online
* from the map. This should be called in long, regular intervals (e.g. every 10 minutes)
* to keep the memory footprint of the plugin low
*/
public void cancelPlayerDataTasks() {
synchronized(playerData) {
Iterator<Map.Entry<Player, NoCheatData>> it = playerData.entrySet().iterator();
while (it.hasNext()) {
cancelTasks(it.next().getValue());
}
}
}
private void cancelTasks(NoCheatData data) {
AirbuildData d = data.airbuild; AirbuildData d = data.airbuild;
if(d != null) { if(d != null) {
int id = d.summaryTask; int id = d.summaryTask;
if(id != -1) { if(id != -1) {
Bukkit.getServer().getScheduler().cancelTask(id); Bukkit.getServer().getScheduler().cancelTask(id);
} } else {
else {
// To prevent accidentially creating a new one while cleaning up // To prevent accidentially creating a new one while cleaning up
d.summaryTask = 1; d.summaryTask = 1;
} }
} }
MovingData d2 = data.moving; MovingData d2 = data.moving;
if(d2 != null) { if(d2 != null) {
int id = d2.summaryTask; int id = d2.summaryTask;
if(id != -1) { if(id != -1) {
Bukkit.getServer().getScheduler().cancelTask(id); Bukkit.getServer().getScheduler().cancelTask(id);
} } else {
else {
// To prevent accidentially creating a new one while cleaning up // To prevent accidentially creating a new one while cleaning up
d2.summaryTask = 1; d2.summaryTask = 1;
} }
} }
} }
} }

View File

@ -7,6 +7,7 @@ import java.util.logging.Formatter;
import java.util.logging.LogRecord; import java.util.logging.LogRecord;
public class LogFileFormatter extends Formatter { public class LogFileFormatter extends Formatter {
private final SimpleDateFormat date; private final SimpleDateFormat date;
public LogFileFormatter() { public LogFileFormatter() {
@ -25,7 +26,7 @@ public class LogFileFormatter extends Formatter {
builder.append(record.getMessage()); builder.append(record.getMessage());
builder.append('\n'); builder.append('\n');
if (ex != null) { if(ex != null) {
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
ex.printStackTrace(new PrintWriter(writer)); ex.printStackTrace(new PrintWriter(writer));
builder.append(writer); builder.append(writer);
@ -33,5 +34,5 @@ public class LogFileFormatter extends Formatter {
return builder.toString(); return builder.toString();
} }
} }

View File

@ -4,12 +4,12 @@ import cc.co.evenprime.bukkit.nocheat.wizard.Wizard;
public class Main { public class Main {
/** /**
* @param args * @param args
*/ */
public static void main(String[] args) { public static void main(String[] args) {
Wizard w = new Wizard(); Wizard w = new Wizard();
w.setVisible(true); w.setVisible(true);
} }
} }

View File

@ -125,7 +125,7 @@ public class NoCheat extends JavaPlugin {
try { try {
dataManager.cancelPlayerDataTasks(); dataManager.cancelPlayerDataTasks();
teardownCleanupTask(); teardownCleanupTask();
teardownServerLagMeasureTask(); teardownServerLagMeasureTask();
} catch(Exception e) { /* Can't do much in case of error here... */ } catch(Exception e) { /* Can't do much in case of error here... */
@ -323,7 +323,9 @@ public class NoCheat extends JavaPlugin {
return false; return false;
if(useNewPermissionSystem) { if(useNewPermissionSystem) {
//System.out.println("New permissions system asked for " + PermissionData.permissionNames[permission] + " got " + player.hasPermission(PermissionData.permissionNames[permission])); // System.out.println("New permissions system asked for " +
// PermissionData.permissionNames[permission] + " got " +
// player.hasPermission(PermissionData.permissionNames[permission]));
return player.hasPermission(PermissionData.permissionNames[permission]); return player.hasPermission(PermissionData.permissionNames[permission]);
} }

View File

@ -3,18 +3,18 @@ package cc.co.evenprime.bukkit.nocheat.actions;
/** /**
* *
* @author Evenprime * @author Evenprime
* *
*/ */
public abstract class Action { public abstract class Action {
public final int firstAfter; public final int firstAfter;
public final boolean repeat; public final boolean repeat;
public Action(int firstAfter, boolean repeat) { public Action(int firstAfter, boolean repeat) {
this.firstAfter = firstAfter; this.firstAfter = firstAfter;
this.repeat = repeat; this.repeat = repeat;
} }
public abstract String getName(); public abstract String getName();
} }

View File

@ -3,15 +3,17 @@ package cc.co.evenprime.bukkit.nocheat.actions;
/** /**
* *
* @author Evenprime * @author Evenprime
* *
*/ */
public class CancelAction extends Action { public class CancelAction extends Action {
public final static CancelAction cancel = new CancelAction(); public final static CancelAction cancel = new CancelAction();
private CancelAction() { super(1, true); } private CancelAction() {
super(1, true);
}
public String getName() { public String getName() {
return "cancel"; return "cancel";
} }
} }

View File

@ -3,31 +3,29 @@ package cc.co.evenprime.bukkit.nocheat.actions;
/** /**
* *
* @author Evenprime * @author Evenprime
* *
*/ */
public class CustomAction extends Action { public class CustomAction extends Action {
public final String command; public final String command;
public CustomAction(int firstAfter, boolean repeat, String command) { public CustomAction(int firstAfter, boolean repeat, String command) {
super(firstAfter, repeat); super(firstAfter, repeat);
this.command = command.trim(); this.command = command.trim();
} }
public String getName() { public String getName() {
return "custom"; return "custom";
} }
public String getValue() { public String getValue() {
if(firstAfter <= 1 && repeat) { if(firstAfter <= 1 && repeat) {
return command; return command;
} } else if(repeat) {
else if(repeat) { return "[" + firstAfter + "] " + command;
return "["+firstAfter+"] "+ command; } else {
} return "[" + firstAfter + "," + repeat + "] " + command;
else { }
return "["+firstAfter+","+repeat+"] "+ command; }
}
}
} }

View File

@ -3,33 +3,33 @@ package cc.co.evenprime.bukkit.nocheat.actions;
/** /**
* *
* @author Evenprime * @author Evenprime
* *
*/ */
import java.util.logging.Level; import java.util.logging.Level;
public class LogAction extends Action { public class LogAction extends Action {
public final Level level; public final Level level;
public final static LogAction loglow = new LogAction(1, false, Level.INFO); public final static LogAction loglow = new LogAction(1, false, Level.INFO);
public final static LogAction logmed = new LogAction(1, false, Level.WARNING); public final static LogAction logmed = new LogAction(1, false, Level.WARNING);
public final static LogAction loghigh = new LogAction(1, false, Level.SEVERE); public final static LogAction loghigh = new LogAction(1, false, Level.SEVERE);
public final static LogAction[] log = { loglow, logmed, loghigh }; public final static LogAction[] log = {loglow, logmed, loghigh};
private LogAction(int firstAfter, boolean repeat, Level level) { private LogAction(int firstAfter, boolean repeat, Level level) {
super(firstAfter, repeat); super(firstAfter, repeat);
this.level = level; this.level = level;
} }
public String getName() { public String getName() {
if(level.equals(Level.INFO)) if(level.equals(Level.INFO))
return "loglow"; return "loglow";
else if(level.equals(Level.WARNING)) else if(level.equals(Level.WARNING))
return "logmed"; return "logmed";
else if(level.equals(Level.SEVERE)) else if(level.equals(Level.SEVERE))
return "loghigh"; return "loghigh";
else else
return ""; return "";
} }
} }

View File

@ -20,130 +20,131 @@ import cc.co.evenprime.bukkit.nocheat.data.AirbuildData;
import cc.co.evenprime.bukkit.nocheat.data.PermissionData; import cc.co.evenprime.bukkit.nocheat.data.PermissionData;
import cc.co.evenprime.bukkit.nocheat.listeners.AirbuildBlockListener; import cc.co.evenprime.bukkit.nocheat.listeners.AirbuildBlockListener;
/** /**
* Check if the player tries to place blocks in midair (which shouldn't be possible) * Check if the player tries to place blocks in midair (which shouldn't be
* possible)
* *
* @author Evenprime * @author Evenprime
* *
*/ */
public class AirbuildCheck extends Check { public class AirbuildCheck extends Check {
// How should airbuild violations be treated? // How should airbuild violations be treated?
private Action actions[][]; private Action actions[][];
private int limits[]; private int limits[];
public AirbuildCheck(NoCheat plugin, NoCheatConfiguration config) { public AirbuildCheck(NoCheat plugin, NoCheatConfiguration config) {
super(plugin, "airbuild", PermissionData.PERMISSION_AIRBUILD, config); super(plugin, "airbuild", PermissionData.PERMISSION_AIRBUILD, config);
} }
public void check(BlockPlaceEvent event) { public void check(BlockPlaceEvent event) {
// Should we check at all? // Should we check at all?
if(skipCheck(event.getPlayer())) return; if(skipCheck(event.getPlayer()))
return;
// Are all 6 sides "air-blocks" -> cancel the event // Are all 6 sides "air-blocks" -> cancel the event
if( event.getBlockAgainst().getType() == Material.AIR && event.getBlockPlaced().getType() != Material.AIR ) { if(event.getBlockAgainst().getType() == Material.AIR && event.getBlockPlaced().getType() != Material.AIR) {
final AirbuildData data = plugin.getDataManager().getAirbuildData(event.getPlayer()); final AirbuildData data = plugin.getDataManager().getAirbuildData(event.getPlayer());
final Player p = event.getPlayer(); final Player p = event.getPlayer();
if(data.summaryTask == -1) { if(data.summaryTask == -1) {
Runnable r = new Runnable() { Runnable r = new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
summary(p, data); summary(p, data);
// deleting its own reference // deleting its own reference
data.summaryTask = -1; data.summaryTask = -1;
}catch(Exception e) {} } catch(Exception e) {}
} }
}; };
// Give a summary in 100 ticks ~ 1 second // Give a summary in 100 ticks ~ 1 second
data.summaryTask = plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, r, 100); data.summaryTask = plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, r, 100);
} }
data.perFiveSeconds++; data.perFiveSeconds++;
// which limit has been reached // which limit has been reached
for(int i = limits.length-1; i >= 0; i--) { for(int i = limits.length - 1; i >= 0; i--) {
if(data.perFiveSeconds >= limits[i]) { if(data.perFiveSeconds >= limits[i]) {
action(actions[i], event, data.perFiveSeconds - limits[i]+1); action(actions[i], event, data.perFiveSeconds - limits[i] + 1);
break; break;
} }
} }
} }
} }
private void action(Action actions[], BlockPlaceEvent event, int violations) { private void action(Action actions[], BlockPlaceEvent event, int violations) {
if(actions == null) return; if(actions == null)
return;
// Execute actions in order // Execute actions in order
for(Action a : actions) { for(Action a : actions) {
if(a.firstAfter <= violations) { if(a.firstAfter <= violations) {
if(a.firstAfter == violations || a.repeat) { if(a.firstAfter == violations || a.repeat) {
if(a instanceof LogAction) { if(a instanceof LogAction) {
final Location l = event.getBlockPlaced().getLocation(); final Location l = event.getBlockPlaced().getLocation();
String logMessage = "Airbuild: "+event.getPlayer().getName()+" tried to place block " + event.getBlockPlaced().getType() + " in the air at " + l.getBlockX() + "," + l.getBlockY() +"," + l.getBlockZ(); String logMessage = "Airbuild: " + event.getPlayer().getName() + " tried to place block " + event.getBlockPlaced().getType() + " in the air at " + l.getBlockX() + "," + l.getBlockY() + "," + l.getBlockZ();
plugin.log(((LogAction)a).level, logMessage); plugin.log(((LogAction) a).level, logMessage);
} } else if(a instanceof CancelAction) {
else if(a instanceof CancelAction) { event.setCancelled(true);
event.setCancelled(true); } else if(a instanceof CustomAction) {
} plugin.handleCustomAction((CustomAction) a, event.getPlayer());
else if(a instanceof CustomAction) { }
plugin.handleCustomAction((CustomAction)a, event.getPlayer()); }
} }
} }
} }
}
}
private void summary(Player player, AirbuildData data) { private void summary(Player player, AirbuildData data) {
// Give a summary according to the highest violation level we encountered in that second // Give a summary according to the highest violation level we
for(int i = limits.length-1; i >= 0; i--) { // encountered in that second
if(data.perFiveSeconds >= limits[i]) { for(int i = limits.length - 1; i >= 0; i--) {
plugin.log(LogAction.log[i].level, "Airbuild summary: " +player.getName() + " total violations per 5 seconds: " + data.perFiveSeconds); if(data.perFiveSeconds >= limits[i]) {
break; plugin.log(LogAction.log[i].level, "Airbuild summary: " + player.getName() + " total violations per 5 seconds: " + data.perFiveSeconds);
} break;
} }
}
data.perFiveSeconds = 0; data.perFiveSeconds = 0;
} }
@Override @Override
public void configure(NoCheatConfiguration config) { public void configure(NoCheatConfiguration config) {
try { try {
limits = new int[3]; limits = new int[3];
limits[0] = config.getIntegerValue("airbuild.limits.low"); limits[0] = config.getIntegerValue("airbuild.limits.low");
limits[1] = config.getIntegerValue("airbuild.limits.med"); limits[1] = config.getIntegerValue("airbuild.limits.med");
limits[2] = config.getIntegerValue("airbuild.limits.high"); limits[2] = config.getIntegerValue("airbuild.limits.high");
actions = new Action[3][]; actions = new Action[3][];
actions[0] = config.getActionValue("airbuild.action.low"); actions[0] = config.getActionValue("airbuild.action.low");
actions[1] = config.getActionValue("airbuild.action.med"); actions[1] = config.getActionValue("airbuild.action.med");
actions[2] = config.getActionValue("airbuild.action.high"); actions[2] = config.getActionValue("airbuild.action.high");
setActive(config.getBooleanValue("active.airbuild")); setActive(config.getBooleanValue("active.airbuild"));
} catch (ConfigurationException e) { } catch(ConfigurationException e) {
setActive(false); setActive(false);
e.printStackTrace(); e.printStackTrace();
} }
} }
@Override @Override
protected void registerListeners() { protected void registerListeners() {
PluginManager pm = Bukkit.getServer().getPluginManager(); PluginManager pm = Bukkit.getServer().getPluginManager();
// Register listeners for airbuild check // Register listeners for airbuild check
pm.registerEvent(Event.Type.BLOCK_PLACE, new AirbuildBlockListener(this), Priority.Low, plugin); pm.registerEvent(Event.Type.BLOCK_PLACE, new AirbuildBlockListener(this), Priority.Low, plugin);
} }
} }

View File

@ -23,98 +23,101 @@ import cc.co.evenprime.bukkit.nocheat.listeners.BogusitemsPlayerListener;
public class BogusitemsCheck extends Check { public class BogusitemsCheck extends Check {
public BogusitemsCheck(NoCheat plugin, NoCheatConfiguration config){ public BogusitemsCheck(NoCheat plugin, NoCheatConfiguration config) {
super(plugin, "bogusitems", PermissionData.PERMISSION_BOGUSITEMS, config); super(plugin, "bogusitems", PermissionData.PERMISSION_BOGUSITEMS, config);
} }
public void check(PlayerPickupItemEvent event) { public void check(PlayerPickupItemEvent event) {
// Should we check at all? // Should we check at all?
if(skipCheck(event.getPlayer())) return; if(skipCheck(event.getPlayer()))
return;
Item i = event.getItem(); Item i = event.getItem();
if(i != null) { if(i != null) {
ItemStack s = i.getItemStack(); ItemStack s = i.getItemStack();
if(s != null) { if(s != null) {
if(s.getAmount() < 0) {// buggy item if(s.getAmount() < 0) {// buggy item
event.getItem().remove(); event.getItem().remove();
event.setCancelled(true); event.setCancelled(true);
plugin.log(Level.WARNING, event.getPlayer().getName() + " tried to pick up an invalid item. Item was removed."); plugin.log(Level.WARNING, event.getPlayer().getName() + " tried to pick up an invalid item. Item was removed.");
cleanPlayerInventory(event.getPlayer()); cleanPlayerInventory(event.getPlayer());
} }
} }
} }
} }
public void check(PlayerInteractEvent event) { public void check(PlayerInteractEvent event) {
if(skipCheck(event.getPlayer())) return; if(skipCheck(event.getPlayer()))
return;
if(event.hasItem() && event.getItem().getAmount() <= 0) {// buggy item if(event.hasItem() && event.getItem().getAmount() <= 0) {// buggy item
event.setCancelled(true); event.setCancelled(true);
plugin.log(Level.WARNING, event.getPlayer().getName() + " tried to use an invalid item. Item was removed."); plugin.log(Level.WARNING, event.getPlayer().getName() + " tried to use an invalid item. Item was removed.");
event.getPlayer().getInventory().remove(event.getItem()); event.getPlayer().getInventory().remove(event.getItem());
cleanPlayerInventory(event.getPlayer()); cleanPlayerInventory(event.getPlayer());
} }
} }
public void check(PlayerDropItemEvent event) { public void check(PlayerDropItemEvent event) {
if(skipCheck(event.getPlayer())) return; if(skipCheck(event.getPlayer()))
return;
Item item = event.getItemDrop(); Item item = event.getItemDrop();
if(item.getItemStack() != null) { if(item.getItemStack() != null) {
ItemStack stack = item.getItemStack(); ItemStack stack = item.getItemStack();
if(stack.getAmount() <= 0) { if(stack.getAmount() <= 0) {
plugin.log(Level.WARNING, event.getPlayer().getName() + " tried to drop an invalid item. Dropped item was changed to dirt."); plugin.log(Level.WARNING, event.getPlayer().getName() + " tried to drop an invalid item. Dropped item was changed to dirt.");
stack.setTypeId(3); // dirt stack.setTypeId(3); // dirt
stack.setAmount(1); stack.setAmount(1);
cleanPlayerInventory(event.getPlayer()); cleanPlayerInventory(event.getPlayer());
} }
} }
} }
private void cleanPlayerInventory(Player player) { private void cleanPlayerInventory(Player player) {
Inventory inv = player.getInventory(); Inventory inv = player.getInventory();
ItemStack stacks[] = inv.getContents(); ItemStack stacks[] = inv.getContents();
for(int i = 0; i < stacks.length; i++) { for(int i = 0; i < stacks.length; i++) {
if(stacks[i] != null && stacks[i].getAmount() <= 0) { if(stacks[i] != null && stacks[i].getAmount() <= 0) {
inv.clear(i); inv.clear(i);
plugin.log(Level.WARNING, "Removed invalid item from inventory of " + player.getName()); plugin.log(Level.WARNING, "Removed invalid item from inventory of " + player.getName());
} }
} }
} }
@Override @Override
public void configure(NoCheatConfiguration config) { public void configure(NoCheatConfiguration config) {
try { try {
setActive(config.getBooleanValue("active.bogusitems")); setActive(config.getBooleanValue("active.bogusitems"));
} catch (ConfigurationException e) { } catch(ConfigurationException e) {
setActive(false); setActive(false);
e.printStackTrace(); e.printStackTrace();
} }
} }
@Override @Override
protected void registerListeners() { protected void registerListeners() {
PluginManager pm = Bukkit.getServer().getPluginManager(); PluginManager pm = Bukkit.getServer().getPluginManager();
// Register listeners for itemdupe check // Register listeners for itemdupe check
Listener bogusitemsPlayerListener = new BogusitemsPlayerListener(this); Listener bogusitemsPlayerListener = new BogusitemsPlayerListener(this);
// Register listeners for itemdupe check // Register listeners for itemdupe check
pm.registerEvent(Event.Type.PLAYER_PICKUP_ITEM, bogusitemsPlayerListener, Priority.Lowest, plugin); pm.registerEvent(Event.Type.PLAYER_PICKUP_ITEM, bogusitemsPlayerListener, Priority.Lowest, plugin);
pm.registerEvent(Event.Type.PLAYER_DROP_ITEM, bogusitemsPlayerListener, Priority.Lowest, plugin); pm.registerEvent(Event.Type.PLAYER_DROP_ITEM, bogusitemsPlayerListener, Priority.Lowest, plugin);
pm.registerEvent(Event.Type.PLAYER_INTERACT, bogusitemsPlayerListener, Priority.Lowest, plugin); pm.registerEvent(Event.Type.PLAYER_INTERACT, bogusitemsPlayerListener, Priority.Lowest, plugin);
} }
} }

View File

@ -1,6 +1,5 @@
package cc.co.evenprime.bukkit.nocheat.checks; package cc.co.evenprime.bukkit.nocheat.checks;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.ConfigurationException; import cc.co.evenprime.bukkit.nocheat.ConfigurationException;
@ -8,64 +7,62 @@ import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.config.NoCheatConfiguration; import cc.co.evenprime.bukkit.nocheat.config.NoCheatConfiguration;
/** /**
* *
* @author Evenprime * @author Evenprime
* *
*/ */
public abstract class Check { public abstract class Check {
private boolean active = false; private boolean active = false;
private boolean listenersRegistered = false; private boolean listenersRegistered = false;
private final int permission; private final int permission;
private final String name; private final String name;
protected final NoCheat plugin; protected final NoCheat plugin;
// Should OPs be checked if Permissions plugin is not available?
public boolean checkOPs;
protected Check(NoCheat plugin, String name, int permission, NoCheatConfiguration config) { // Should OPs be checked if Permissions plugin is not available?
this.plugin = plugin; public boolean checkOPs;
this.permission = permission;
this.name = name;
try { protected Check(NoCheat plugin, String name, int permission, NoCheatConfiguration config) {
checkOPs= config.getBooleanValue(name + ".checkops"); this.plugin = plugin;
} catch (ConfigurationException e) { this.permission = permission;
checkOPs = false; this.name = name;
}
configure(config);
}
public boolean skipCheck(Player player) { try {
// Should we check at all? checkOPs = config.getBooleanValue(name + ".checkops");
return !active || plugin.hasPermission(player, permission, checkOPs); } catch(ConfigurationException e) {
} checkOPs = false;
}
protected abstract void configure(NoCheatConfiguration config);
protected abstract void registerListeners(); configure(config);
}
public boolean isActive() { public boolean skipCheck(Player player) {
return active; // Should we check at all?
} return !active || plugin.hasPermission(player, permission, checkOPs);
}
protected void setActive(boolean active) { protected abstract void configure(NoCheatConfiguration config);
synchronized(this) {
if(active && !listenersRegistered) {
listenersRegistered = true;
registerListeners();
}
}
// There is no way to unregister listeners ... protected abstract void registerListeners();
this.active = active;
}
public String getName() { public boolean isActive() {
return name; return active;
} }
protected void setActive(boolean active) {
synchronized(this) {
if(active && !listenersRegistered) {
listenersRegistered = true;
registerListeners();
}
}
// There is no way to unregister listeners ...
this.active = active;
}
public String getName() {
return name;
}
} }

View File

@ -1,109 +1,118 @@
package cc.co.evenprime.bukkit.nocheat.checks; package cc.co.evenprime.bukkit.nocheat.checks;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.data.MovingData; import cc.co.evenprime.bukkit.nocheat.data.MovingData;
/** /**
* Check if the player should be allowed to make that move, e.g. is he allowed to jump here or move that far in one step * Check if the player should be allowed to make that move, e.g. is he allowed
* to jump here or move that far in one step
* *
* @author Evenprime * @author Evenprime
* *
*/ */
public class FlyingCheck { public class FlyingCheck {
public FlyingCheck() { } public FlyingCheck() {}
// How many move events can a player have in air before he is expected to lose altitude (or eventually land somewhere) // How many move events can a player have in air before he is expected to
private final static int jumpingLimit = 5; // lose altitude (or eventually land somewhere)
private final static int jumpingLimit = 5;
// How high may a player get compared to his last location with ground contact // How high may a player get compared to his last location with ground
private final static double jumpHeight = 1.31D; // contact
private final static double jumpHeight = 1.31D;
// How much points should hovering attempts cause? // How much points should hovering attempts cause?
private final static double hoveringPunishment = 0.2D; private final static double hoveringPunishment = 0.2D;
// How high may a player move in one event on ground
private final static double stepHeight = 0.501D;
// How high may a player move in one event on ground
private final static double stepHeight = 0.501D;
/** /**
* Calculate if and how much the player "failed" this check. The check should not * Calculate if and how much the player "failed" this check. The check
* modify any data * should not
* * modify any data
*/ *
public double check(final Player player, final Location from, final boolean fromOnGround, final Location to, final boolean toOnGround, final MovingData data) { */
public double check(final Player player, final Location from, final boolean fromOnGround, final Location to, final boolean toOnGround, final MovingData data) {
// How much higher did the player move than expected?? // How much higher did the player move than expected??
double distanceAboveLimit = 0.0D; double distanceAboveLimit = 0.0D;
final double toY = to.getY();
final double fromY = from.getY();
double limit = calculateVerticalLimit(data, fromOnGround) + jumpHeight; final double toY = to.getY();
final double fromY = from.getY();
// Walk or start Jump
if(fromOnGround)
{
distanceAboveLimit = toY - Math.floor(fromY) - limit;
}
// Land or Fly/Fall
else
{
final Location l;
if(data.setBackPoint == null) double limit = calculateVerticalLimit(data, fromOnGround) + jumpHeight;
l = from;
else
l = data.setBackPoint;
if(data.jumpPhase > jumpingLimit) { // Walk or start Jump
limit -= (data.jumpPhase-jumpingLimit) * 0.2D; if(fromOnGround) {
} distanceAboveLimit = toY - Math.floor(fromY) - limit;
}
// Land or Fly/Fall
else {
final Location l;
if(toOnGround) limit += stepHeight; if(data.setBackPoint == null)
l = from;
else
l = data.setBackPoint;
distanceAboveLimit = toY - Math.floor(l.getY()) - limit; if(data.jumpPhase > jumpingLimit) {
limit -= (data.jumpPhase - jumpingLimit) * 0.2D;
}
// Always give some bonus points in case of identical Y values in midair (hovering player) if(toOnGround)
if(fromY == toY && !toOnGround) { limit += stepHeight;
distanceAboveLimit = Math.max(hoveringPunishment, distanceAboveLimit+hoveringPunishment);
}
}
return distanceAboveLimit; distanceAboveLimit = toY - Math.floor(l.getY()) - limit;
}
private double calculateVerticalLimit(final MovingData data, final boolean onGroundFrom) { // Always give some bonus points in case of identical Y values in
// midair (hovering player)
if(fromY == toY && !toOnGround) {
distanceAboveLimit = Math.max(hoveringPunishment, distanceAboveLimit + hoveringPunishment);
}
}
// A halfway lag-resistant method of allowing vertical acceleration without allowing blatant cheating return distanceAboveLimit;
}
// FACT: Minecraft server sends player "velocity" to the client and lets the client calculate the movement private double calculateVerticalLimit(final MovingData data, final boolean onGroundFrom) {
// PROBLEM: There may be an arbitrary amount of other move events between the server sending the data
// and the client accepting it/reacting to it. The server can't know when the client starts to
// consider the sent "velocity" in its movement.
// SOLUTION: Give the client at least 10 events after sending "velocity" to actually use the velocity for
// its movement, plus additional events if the "velocity" was big and can cause longer flights
// The server sent the player a "velocity" packet a short time ago // A halfway lag-resistant method of allowing vertical acceleration
// without allowing blatant cheating
// consume a counter for this client // FACT: Minecraft server sends player "velocity" to the client and lets
if(data.vertFreedomCounter > 0) { // the client calculate the movement
data.vertFreedomCounter--; // PROBLEM: There may be an arbitrary amount of other move events
data.vertFreedom += data.maxYVelocity*2D; // between the server sending the data
data.maxYVelocity *= 0.90D; // and the client accepting it/reacting to it. The server can't know
} // when the client starts to
// consider the sent "velocity" in its movement.
final double limit = data.vertFreedom; // SOLUTION: Give the client at least 10 events after sending "velocity"
// to actually use the velocity for
// its movement, plus additional events if the "velocity" was big and
// can cause longer flights
// If the event counter has been consumed, remove the vertical movement limit increase when landing the next time // The server sent the player a "velocity" packet a short time ago
if(onGroundFrom && data.vertFreedomCounter <= 0) {
data.vertFreedom = 0.0D; // consume a counter for this client
} if(data.vertFreedomCounter > 0) {
data.vertFreedomCounter--;
data.vertFreedom += data.maxYVelocity * 2D;
data.maxYVelocity *= 0.90D;
}
final double limit = data.vertFreedom;
// If the event counter has been consumed, remove the vertical movement
// limit increase when landing the next time
if(onGroundFrom && data.vertFreedomCounter <= 0) {
data.vertFreedom = 0.0D;
}
return limit;
}
return limit;
}
} }

View File

@ -1,4 +1,3 @@
package cc.co.evenprime.bukkit.nocheat.checks; package cc.co.evenprime.bukkit.nocheat.checks;
import java.util.Locale; import java.util.Locale;
@ -27,10 +26,11 @@ import cc.co.evenprime.bukkit.nocheat.listeners.MovingPlayerListener;
import cc.co.evenprime.bukkit.nocheat.listeners.MovingPlayerMonitor; import cc.co.evenprime.bukkit.nocheat.listeners.MovingPlayerMonitor;
/** /**
* Check if the player should be allowed to make that move, e.g. is he allowed to jump here or move that far in one step * Check if the player should be allowed to make that move, e.g. is he allowed
* to jump here or move that far in one step
* *
* @author Evenprime * @author Evenprime
* *
*/ */
public class MovingCheck extends Check { public class MovingCheck extends Check {
@ -42,33 +42,37 @@ public class MovingCheck extends Check {
runningCheck = new RunningCheck(); runningCheck = new RunningCheck();
} }
private int ticksBeforeSummary; private int ticksBeforeSummary;
public long statisticElapsedTimeNano = 0; public long statisticElapsedTimeNano = 0;
public boolean allowFlying; public boolean allowFlying;
public boolean allowFakeSneak; public boolean allowFakeSneak;
public boolean allowFastSwim; public boolean allowFastSwim;
public double stepWidth; public double stepWidth;
public double sneakWidth; public double sneakWidth;
public double swimWidth; public double swimWidth;
private boolean waterElevators; private boolean waterElevators;
private String logMessage; private String logMessage;
private String summaryMessage; private String summaryMessage;
// How should moving violations be treated? // How should moving violations be treated?
private Action actions[][]; private Action actions[][];
public long statisticTotalEvents = 1; // Prevent accidental division by 0 at some point public long statisticTotalEvents = 1; // Prevent
// accidental
// division by
// 0 at some
// point
private boolean enforceTeleport; private boolean enforceTeleport;
private final MovingEventHelper helper; private final MovingEventHelper helper;
private final FlyingCheck flyingCheck; private final FlyingCheck flyingCheck;
private final RunningCheck runningCheck; private final RunningCheck runningCheck;
/** /**
* The actual check. * The actual check.
@ -76,28 +80,29 @@ public class MovingCheck extends Check {
* Second check if the player moved too far horizontally * Second check if the player moved too far horizontally
* Third check if the player moved too high vertically * Third check if the player moved too high vertically
* Fourth treat any occured violations as configured * Fourth treat any occured violations as configured
*
* @param event * @param event
*/ */
public Location check(Player player, Location from, Location to, public Location check(Player player, Location from, Location to, MovingData data) {
MovingData data) {
Location newToLocation = null; Location newToLocation = null;
final long startTime = System.nanoTime(); final long startTime = System.nanoTime();
/************* DECIDE WHICH CHECKS NEED TO BE RUN *************/ /************* DECIDE WHICH CHECKS NEED TO BE RUN *************/
final boolean flyCheck = !allowFlying && !plugin.hasPermission(player, PermissionData.PERMISSION_FLYING, checkOPs); final boolean flyCheck = !allowFlying && !plugin.hasPermission(player, PermissionData.PERMISSION_FLYING, checkOPs);
final boolean runCheck = true; final boolean runCheck = true;
/***************** REFINE EVENT DATA FOR CHECKS ***************/ /***************** REFINE EVENT DATA FOR CHECKS ***************/
if(flyCheck || runCheck) { if(flyCheck || runCheck) {
// In both cases it will be interesting to know the type of underground the player // In both cases it will be interesting to know the type of
// underground the player
// is in or goes to // is in or goes to
final int fromType = helper.isLocationOnGround(from.getWorld(), from.getX(), from.getY(), from.getZ(), waterElevators); final int fromType = helper.isLocationOnGround(from.getWorld(), from.getX(), from.getY(), from.getZ(), waterElevators);
final int toType = helper.isLocationOnGround(to.getWorld(), to.getX(), to.getY(),to.getZ(), waterElevators); final int toType = helper.isLocationOnGround(to.getWorld(), to.getX(), to.getY(), to.getZ(), waterElevators);
final boolean fromOnGround = fromType != MovingEventHelper.NONSOLID; final boolean fromOnGround = fromType != MovingEventHelper.NONSOLID;
final boolean toOnGround = toType != MovingEventHelper.NONSOLID; final boolean toOnGround = toType != MovingEventHelper.NONSOLID;
@ -109,16 +114,14 @@ public class MovingCheck extends Check {
if(flyCheck) { if(flyCheck) {
result += Math.max(0D, flyingCheck.check(player, from, fromOnGround, to, toOnGround, data)); result += Math.max(0D, flyingCheck.check(player, from, fromOnGround, to, toOnGround, data));
} } else {
else // If players are allowed to fly, there's no need to remember
{ // the last location on ground
// If players are allowed to fly, there's no need to remember the last location on ground
data.setBackPoint = from; data.setBackPoint = from;
} }
if(runCheck) { if(runCheck) {
result += Math.max(0D, runningCheck.check(from, to, result += Math.max(0D, runningCheck.check(from, to, !allowFakeSneak && player.isSneaking(), !allowFastSwim && (fromType & toType & MovingEventHelper.LIQUID) > 0, data, this));
!allowFakeSneak && player.isSneaking(), !allowFastSwim && (fromType & toType & MovingEventHelper.LIQUID) > 0, data, this));
} }
/********* HANDLE/COMBINE THE RESULTS OF THE CHECKS ***********/ /********* HANDLE/COMBINE THE RESULTS OF THE CHECKS ***********/
@ -128,22 +131,22 @@ public class MovingCheck extends Check {
if(fromOnGround) { if(fromOnGround) {
data.setBackPoint = from; data.setBackPoint = from;
data.jumpPhase = 0; data.jumpPhase = 0;
} } else if(result <= 0 && toOnGround) {
else if(result <= 0 && toOnGround) {
data.jumpPhase = 0; data.jumpPhase = 0;
} }
if(result > 0) { if(result > 0) {
// Increment violation counter // Increment violation counter
data.violationLevel += result; data.violationLevel += result;
if(data.setBackPoint == null) data.setBackPoint = from; if(data.setBackPoint == null)
data.setBackPoint = from;
} }
if(result > 0 && data.violationLevel > 1) { if(result > 0 && data.violationLevel > 1) {
setupSummaryTask(player, data); setupSummaryTask(player, data);
int level = limitCheck(data.violationLevel-1); int level = limitCheck(data.violationLevel - 1);
data.violationsInARow[level]++; data.violationsInARow[level]++;
@ -158,12 +161,13 @@ public class MovingCheck extends Check {
statisticElapsedTimeNano += System.nanoTime() - startTime; statisticElapsedTimeNano += System.nanoTime() - startTime;
statisticTotalEvents++; statisticTotalEvents++;
return newToLocation; return newToLocation;
} }
/** /**
* Various corner cases that would cause this check to fail or require special treatment * Various corner cases that would cause this check to fail or require
* special treatment
*
* @param player * @param player
* @param data * @param data
* @param from * @param from
@ -172,34 +176,14 @@ public class MovingCheck extends Check {
*/ */
public boolean shouldBeApplied(final Player player, final MovingData data, final Location from, final Location to) { public boolean shouldBeApplied(final Player player, final MovingData data, final Location from, final Location to) {
if(player.isDead() || player.isInsideVehicle()) return false;
if(data.wasTeleported) {
// Remember this location
data.teleportedTo = from.clone();
data.wasTeleported = false;
data.jumpPhase = 0;
}
if(data.teleportedTo != null && data.teleportedTo.getWorld().equals(from.getWorld())) {
// As long as the from-Location doesn't change, the player didn't accept the teleport
if(data.teleportedTo.distanceSquared(from) < 0.01D) {
// Event after Teleport ignored
return false;
}
else {
// The player finally accepted the teleport with the previous event
data.teleportedTo = null;
}
}
return true; return true;
} }
/** /**
* Register a task with bukkit that will be run a short time from now, displaying how many * Register a task with bukkit that will be run a short time from now,
* displaying how many
* violations happened in that timeframe * violations happened in that timeframe
*
* @param p * @param p
* @param data * @param data
*/ */
@ -213,7 +197,7 @@ public class MovingCheck extends Check {
try { try {
if(data.highestLogLevel != null) { if(data.highestLogLevel != null) {
String logString = String.format(summaryMessage, p.getName(), ticksBeforeSummary/20, data.violationsInARow[0], data.violationsInARow[1],data.violationsInARow[2]); String logString = String.format(summaryMessage, p.getName(), ticksBeforeSummary / 20, data.violationsInARow[0], data.violationsInARow[1], data.violationsInARow[2]);
plugin.log(data.highestLogLevel, logString); plugin.log(data.highestLogLevel, logString);
data.highestLogLevel = Level.ALL; data.highestLogLevel = Level.ALL;
@ -224,8 +208,7 @@ public class MovingCheck extends Check {
data.violationsInARow[0] = 0; data.violationsInARow[0] = 0;
data.violationsInARow[1] = 0; data.violationsInARow[1] = 0;
data.violationsInARow[2] = 0; data.violationsInARow[2] = 0;
} } catch(Exception e) {}
catch(Exception e) { }
} }
}; };
@ -235,7 +218,8 @@ public class MovingCheck extends Check {
} }
/** /**
* Call this when a player got successfully teleported with the corresponding event to adjust stored * Call this when a player got successfully teleported with the
* corresponding event to adjust stored
* data to the new situation * data to the new situation
* *
* @param event * @param event
@ -244,32 +228,34 @@ public class MovingCheck extends Check {
MovingData data = plugin.getDataManager().getMovingData(event.getPlayer()); MovingData data = plugin.getDataManager().getMovingData(event.getPlayer());
// We can enforce a teleport, if that flag is explicitly set (but I'd rather have other plugins // We can enforce a teleport, if that flag is explicitly set (but I'd
// rather have other plugins
// not arbitrarily cancel teleport events in the first place... // not arbitrarily cancel teleport events in the first place...
if(data.teleportInitializedByMe != null && event.isCancelled() && enforceTeleport && event.getTo().equals(data.teleportInitializedByMe)) { if(data.teleportInitializedByMe != null && event.isCancelled() && enforceTeleport && event.getTo().equals(data.teleportInitializedByMe)) {
event.setCancelled(false); event.setCancelled(false);
data.teleportInitializedByMe = null; data.teleportInitializedByMe = null;
} }
if(!event.isCancelled()) { if(!event.isCancelled()) {
data.wasTeleported = true; data.setBackPoint = null;
data.setBackPoint = event.getTo().clone();
//data.lastLocation = event.getTo().clone();
} }
// reset anyway - if another plugin cancelled our teleport it's no use to try and be precise // reset anyway - if another plugin cancelled our teleport it's no use
// to try and be precise
data.jumpPhase = 0; data.jumpPhase = 0;
} }
/** /**
* Update the cached values for players velocity to be prepared to * Update the cached values for players velocity to be prepared to
* give them additional movement freedom in their next move events * give them additional movement freedom in their next move events
*
* @param v * @param v
* @param data * @param data
*/ */
public void updateVelocity(Vector v, MovingData data) { public void updateVelocity(Vector v, MovingData data) {
// Compare the velocity vector to the existing movement freedom that we've from previous events // Compare the velocity vector to the existing movement freedom that
// we've from previous events
double tmp = (Math.abs(v.getX()) + Math.abs(v.getZ())) * 3D; double tmp = (Math.abs(v.getX()) + Math.abs(v.getZ())) * 3D;
if(tmp > data.horizFreedom) if(tmp > data.horizFreedom)
data.horizFreedom = tmp; data.horizFreedom = tmp;
@ -282,58 +268,67 @@ public class MovingCheck extends Check {
/** /**
* Perform actions that were specified in the config file * Perform actions that were specified in the config file
*
* @param event * @param event
* @param action * @param action
* @return * @return
*/ */
private Location action( Player player, Location from, Location to, Action[] actions, int violations, MovingData data, MovingEventHelper helper) { private Location action(Player player, Location from, Location to, Action[] actions, int violations, MovingData data, MovingEventHelper helper) {
Location newToLocation = null; Location newToLocation = null;
if(actions == null) return newToLocation; if(actions == null)
return newToLocation;
boolean cancelled = false; boolean cancelled = false;
for(Action a : actions) { for(Action a : actions) {
if(a.firstAfter <= violations) { if(a.firstAfter <= violations) {
if(a.firstAfter == violations || a.repeat) { if(a.firstAfter == violations || a.repeat) {
if(a instanceof LogAction) { if(a instanceof LogAction) {
// prepare log message if necessary // prepare log message if necessary
String log = String.format(Locale.US, logMessage, player.getName(), from.getWorld().getName(), to.getWorld().getName(), from.getX(), from.getY(), from.getZ(), to.getX(), to.getY(), to.getZ(), Math.abs(from.getX()-to.getX()),to.getY()-from.getY(), Math.abs(from.getZ()-to.getZ())); String log = String.format(Locale.US, logMessage, player.getName(), from.getWorld().getName(), to.getWorld().getName(), from.getX(), from.getY(), from.getZ(), to.getX(), to.getY(), to.getZ(), Math.abs(from.getX() - to.getX()), to.getY() - from.getY(), Math.abs(from.getZ() - to.getZ()));
plugin.log(((LogAction)a).level, log); plugin.log(((LogAction) a).level, log);
// Remember the highest log level we encountered to determine what level the summary log message should have // Remember the highest log level we encountered to
if(data.highestLogLevel == null) data.highestLogLevel = Level.ALL; // determine what level the summary log message should
if(data.highestLogLevel.intValue() < ((LogAction)a).level.intValue()) data.highestLogLevel = ((LogAction)a).level; // have
} if(data.highestLogLevel == null)
else if(!cancelled && a instanceof CancelAction) { data.highestLogLevel = Level.ALL;
// Make a modified copy of the setBackPoint to prevent other plugins from accidentally modifying it if(data.highestLogLevel.intValue() < ((LogAction) a).level.intValue())
// and keep the current pitch and yaw (setbacks "feel" better that way). Plus try to adapt the Y-coord data.highestLogLevel = ((LogAction) a).level;
} else if(!cancelled && a instanceof CancelAction) {
// Make a modified copy of the setBackPoint to prevent
// other plugins from accidentally modifying it
// and keep the current pitch and yaw (setbacks "feel"
// better that way). Plus try to adapt the Y-coord
// to place the player close to ground // to place the player close to ground
double y = data.setBackPoint.getY(); double y = data.setBackPoint.getY();
// search for the first solid block up to 5 blocks below the setbackpoint and teleport the player there // search for the first solid block up to 5 blocks below
// the setbackpoint and teleport the player there
int i = 0; int i = 0;
for(; i < 20; i++) { for(; i < 20; i++) {
if(helper.isLocationOnGround(data.setBackPoint.getWorld(), data.setBackPoint.getX(), data.setBackPoint.getY() - 0.5*i, data.setBackPoint.getZ(), waterElevators) != MovingData.NONSOLID) { if(helper.isLocationOnGround(data.setBackPoint.getWorld(), data.setBackPoint.getX(), data.setBackPoint.getY() - 0.5 * i, data.setBackPoint.getZ(), waterElevators) != MovingData.NONSOLID) {
break; break;
} }
} }
y -= 0.5*i; y -= 0.5 * i;
data.setBackPoint.setY(y); data.setBackPoint.setY(y);
// Remember the location we send the player to, to identify teleports that were started by us // Remember the location we send the player to, to
// identify teleports that were started by us
data.teleportInitializedByMe = new Location(data.setBackPoint.getWorld(), data.setBackPoint.getX(), y, data.setBackPoint.getZ(), to.getYaw(), to.getPitch()); data.teleportInitializedByMe = new Location(data.setBackPoint.getWorld(), data.setBackPoint.getX(), y, data.setBackPoint.getZ(), to.getYaw(), to.getPitch());
newToLocation = data.teleportInitializedByMe; newToLocation = data.teleportInitializedByMe;
cancelled = true; // just prevent us from treating more than one "cancel" action, which would make no sense cancelled = true; // just prevent us from treating more
} // than one "cancel" action, which
else if(a instanceof CustomAction) // would make no sense
plugin.handleCustomAction((CustomAction)a, player); } else if(a instanceof CustomAction)
plugin.handleCustomAction((CustomAction) a, player);
} }
} }
} }
@ -344,6 +339,7 @@ public class MovingCheck extends Check {
/** /**
* Check a value against an array of sorted values to find out * Check a value against an array of sorted values to find out
* where it fits in * where it fits in
*
* @param value * @param value
* @param limits * @param limits
* @return * @return
@ -352,10 +348,12 @@ public class MovingCheck extends Check {
if(value > 0.0D) { if(value > 0.0D) {
if(value > 0.5D) { if(value > 0.5D) {
if(value > 2.0D) if(value > 2.0D)
return 2; return 2;
return 1; } return 1;
return 0; } }
return 0;
}
return -1; return -1;
} }
@ -371,19 +369,11 @@ public class MovingCheck extends Check {
checkOPs = config.getBooleanValue("moving.checkops"); checkOPs = config.getBooleanValue("moving.checkops");
logMessage = config.getStringValue("moving.logmessage"). logMessage = config.getStringValue("moving.logmessage").replace("[player]", "%1$s").replace("[world]", "%2$s").replace("[from]", "(%4$.1f, %5$.1f, %6$.1f)").replace("[to]", "(%7$.1f, %8$.1f, %9$.1f)").replace("[distance]", "(%10$.1f, %11$.1f, %12$.1f)");
replace("[player]", "%1$s").
replace("[world]", "%2$s").
replace("[from]", "(%4$.1f, %5$.1f, %6$.1f)").
replace("[to]", "(%7$.1f, %8$.1f, %9$.1f)").
replace("[distance]", "(%10$.1f, %11$.1f, %12$.1f)");
summaryMessage = config.getStringValue("moving.summarymessage"). summaryMessage = config.getStringValue("moving.summarymessage").replace("[timeframe]", "%2$d").replace("[player]", "%1$s").replace("[violations]", "(%3$d,%4$d,%5$d)");
replace("[timeframe]", "%2$d").
replace("[player]", "%1$s").
replace("[violations]", "(%3$d,%4$d,%5$d)");
ticksBeforeSummary = config.getIntegerValue("moving.summaryafter")*20; ticksBeforeSummary = config.getIntegerValue("moving.summaryafter") * 20;
actions = new Action[3][]; actions = new Action[3][];
@ -395,11 +385,11 @@ public class MovingCheck extends Check {
enforceTeleport = config.getBooleanValue("moving.enforceteleport"); enforceTeleport = config.getBooleanValue("moving.enforceteleport");
stepWidth = ((double)config.getIntegerValue("moving.limits.walking")) /100D; stepWidth = ((double) config.getIntegerValue("moving.limits.walking")) / 100D;
sneakWidth = ((double)config.getIntegerValue("moving.limits.sneaking"))/100D; sneakWidth = ((double) config.getIntegerValue("moving.limits.sneaking")) / 100D;
swimWidth = ((double)config.getIntegerValue("moving.limits.swimming"))/100D; swimWidth = ((double) config.getIntegerValue("moving.limits.swimming")) / 100D;
} catch (ConfigurationException e) { } catch(ConfigurationException e) {
setActive(false); setActive(false);
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -7,164 +7,160 @@ import org.bukkit.World;
/** /**
* A collection of stuff to process data of move events * A collection of stuff to process data of move events
*
* @author Evenprime * @author Evenprime
* *
*/ */
public class MovingEventHelper { public class MovingEventHelper {
private final double magic = 0.30000001192092896D; private final double magic = 0.30000001192092896D;
private final double magic2 = 0.69999998807907103D; private final double magic2 = 0.69999998807907103D;
// Block types that may need to be treated specially
public static final int NONSOLID = 0; // 0x00000000
public static final int SOLID = 1; // 0x00000001
public static final int LIQUID = 2; // 0x00000010
public static final int LADDER = 4; // 0x00000100
public static final int FENCE = 8; // 0x00001000
// Until I can think of a better way to determine if a block is solid or not, this is what I'll do
private final int types[] = new int[256];
public MovingEventHelper() { // Block types that may need to be treated specially
// Find and define properties of all blocks public static final int NONSOLID = 0; // 0x00000000
for(int i = 0; i < types.length; i++) { public static final int SOLID = 1; // 0x00000001
public static final int LIQUID = 2; // 0x00000010
// Everything is considered nonsolid at first public static final int LADDER = 4; // 0x00000100
types[i] = NONSOLID; public static final int FENCE = 8; // 0x00001000
if(Block.byId[i] != null) {
if(Block.byId[i].material.isSolid()) {
// solid blocks like STONE, CAKE, TRAPDOORS
types[i] = SOLID;
}
else if(Block.byId[i].material.isLiquid()){
// WATER, LAVA
types[i] = LIQUID;
}
}
}
// Special types just for me
types[Material.LADDER.getId()]= LADDER | SOLID;
types[Material.FENCE.getId()]= FENCE | SOLID;
}
/**
* Check if certain coordinates are considered "on ground"
*
* @param w The world the coordinates belong to
* @param values The coordinates [lowerX, higherX, Y, lowerZ, higherZ] to be checked
* @param l The precise location that was used for calculation of "values"
* @return
*/
public int isLocationOnGround(final World world, final double x, final double y, final double z, boolean waterElevatorsAllowed) {
final int lowerX = lowerBorder(x); // Until I can think of a better way to determine if a block is solid or
final int upperX = upperBorder(x); // not, this is what I'll do
final int Y = (int)Math.floor(y); private final int types[] = new int[256];
final int lowerZ = lowerBorder(z);
final int higherZ = upperBorder(z);
public MovingEventHelper() {
// Find and define properties of all blocks
for(int i = 0; i < types.length; i++) {
int result; // Everything is considered nonsolid at first
types[i] = NONSOLID;
// check in what kind of block the player is standing "in" if(Block.byId[i] != null) {
result = types[world.getBlockTypeIdAt(lowerX, Y, lowerZ)] | types[world.getBlockTypeIdAt(upperX, Y, lowerZ)] | if(Block.byId[i].material.isSolid()) {
types[world.getBlockTypeIdAt(lowerX, Y, higherZ)] | types[world.getBlockTypeIdAt(upperX, Y, higherZ)]; // solid blocks like STONE, CAKE, TRAPDOORS
types[i] = SOLID;
} else if(Block.byId[i].material.isLiquid()) {
// WATER, LAVA
types[i] = LIQUID;
}
}
}
if((result & SOLID) != 0) { // Special types just for me
// return standing types[Material.LADDER.getId()] = LADDER | SOLID;
return SOLID; types[Material.FENCE.getId()] = FENCE | SOLID;
} }
else if((result & LIQUID) != 0) {
// return swimming
return LIQUID;
}
// Check the four borders of the players hitbox for something he could be standing on /**
result = types[world.getBlockTypeIdAt(lowerX, Y-1, lowerZ)] | types[world.getBlockTypeIdAt(upperX, Y-1, lowerZ)] | * Check if certain coordinates are considered "on ground"
types[world.getBlockTypeIdAt(lowerX, Y-1, higherZ)] | types[world.getBlockTypeIdAt(upperX, Y-1, higherZ)]; *
* @param w
* The world the coordinates belong to
* @param values
* The coordinates [lowerX, higherX, Y, lowerZ, higherZ] to be
* checked
* @param l
* The precise location that was used for calculation of "values"
* @return
*/
public int isLocationOnGround(final World world, final double x, final double y, final double z, boolean waterElevatorsAllowed) {
if((result & SOLID) != 0) { final int lowerX = lowerBorder(x);
// return standing final int upperX = upperBorder(x);
return SOLID; final int Y = (int) Math.floor(y);
} final int lowerZ = lowerBorder(z);
final int higherZ = upperBorder(z);
int result;
// check if his head is "stuck" in an block // check in what kind of block the player is standing "in"
result = types[world.getBlockTypeIdAt(lowerX, Y+1, lowerZ)] | types[world.getBlockTypeIdAt(upperX, Y+1, lowerZ)] | result = types[world.getBlockTypeIdAt(lowerX, Y, lowerZ)] | types[world.getBlockTypeIdAt(upperX, Y, lowerZ)] | types[world.getBlockTypeIdAt(lowerX, Y, higherZ)] | types[world.getBlockTypeIdAt(upperX, Y, higherZ)];
types[world.getBlockTypeIdAt(lowerX, Y+1, higherZ)] | types[world.getBlockTypeIdAt(upperX, Y+1, higherZ)];
if((result & SOLID) != 0) { if((result & SOLID) != 0) {
// return standing // return standing
return SOLID; return SOLID;
} } else if((result & LIQUID) != 0) {
else if((result & LIQUID) != 0) { // return swimming
// return swimming return LIQUID;
return LIQUID; }
}
// Running on fences causes problems if not treated specially // Check the four borders of the players hitbox for something he could
result = types[world.getBlockTypeIdAt(lowerX, Y-2, lowerZ)] | types[world.getBlockTypeIdAt(upperX, Y-2, lowerZ)] | // be standing on
types[world.getBlockTypeIdAt(lowerX, Y-2, higherZ)] | types[world.getBlockTypeIdAt(upperX, Y-2, higherZ)]; result = types[world.getBlockTypeIdAt(lowerX, Y - 1, lowerZ)] | types[world.getBlockTypeIdAt(upperX, Y - 1, lowerZ)] | types[world.getBlockTypeIdAt(lowerX, Y - 1, higherZ)] | types[world.getBlockTypeIdAt(upperX, Y - 1, higherZ)];
if((result & FENCE) != 0) { if((result & SOLID) != 0) {
// return standing // return standing
return SOLID; return SOLID;
} }
// Water elevators - optional "feature" // check if his head is "stuck" in an block
if(waterElevatorsAllowed) { result = types[world.getBlockTypeIdAt(lowerX, Y + 1, lowerZ)] | types[world.getBlockTypeIdAt(upperX, Y + 1, lowerZ)] | types[world.getBlockTypeIdAt(lowerX, Y + 1, higherZ)] | types[world.getBlockTypeIdAt(upperX, Y + 1, higherZ)];
result = types[world.getBlockTypeIdAt(lowerX+1, Y+1, lowerZ+1)] |
types[world.getBlockTypeIdAt(lowerX+1, Y , lowerZ+1)] |
types[world.getBlockTypeIdAt(lowerX, Y+1, lowerZ+1)] |
types[world.getBlockTypeIdAt(lowerX , Y , lowerZ+1)] |
types[world.getBlockTypeIdAt(lowerX+1, Y+1, lowerZ )] |
types[world.getBlockTypeIdAt(lowerX+1, Y , lowerZ )] ;
if((result & LIQUID) != 0) { if((result & SOLID) != 0) {
return SOLID; // Solid? Why that? Because that's closer to what the bug actually does than liquid // return standing
} return SOLID;
} } else if((result & LIQUID) != 0) {
// If nothing matches, he is somewhere in the air // return swimming
return NONSOLID; return LIQUID;
} }
/**
* Personal Rounding function to determine if a player is still touching a block or not
* @param d1
* @return
*/
private int lowerBorder(double d1) {
double floor = Math.floor(d1); // Running on fences causes problems if not treated specially
double d4 = floor + magic; result = types[world.getBlockTypeIdAt(lowerX, Y - 2, lowerZ)] | types[world.getBlockTypeIdAt(upperX, Y - 2, lowerZ)] | types[world.getBlockTypeIdAt(lowerX, Y - 2, higherZ)] | types[world.getBlockTypeIdAt(upperX, Y - 2, higherZ)];
if(d4 <= d1) if((result & FENCE) != 0) {
d4 = 0; // return standing
else return SOLID;
d4 = 1; }
return (int) (floor - d4); // Water elevators - optional "feature"
} if(waterElevatorsAllowed) {
result = types[world.getBlockTypeIdAt(lowerX + 1, Y + 1, lowerZ + 1)] | types[world.getBlockTypeIdAt(lowerX + 1, Y, lowerZ + 1)] | types[world.getBlockTypeIdAt(lowerX, Y + 1, lowerZ + 1)] | types[world.getBlockTypeIdAt(lowerX, Y, lowerZ + 1)] | types[world.getBlockTypeIdAt(lowerX + 1, Y + 1, lowerZ)] | types[world.getBlockTypeIdAt(lowerX + 1, Y, lowerZ)];
/** if((result & LIQUID) != 0) {
* Personal Rounding function to determine if a player is still touching a block or not return SOLID; // Solid? Why that? Because that's closer to what
* @param d1 // the bug actually does than liquid
* @return }
*/ }
private int upperBorder(double d1) { // If nothing matches, he is somewhere in the air
return NONSOLID;
}
double floor = Math.floor(d1); /**
double d4 = floor + magic2; * Personal Rounding function to determine if a player is still touching a
* block or not
*
* @param d1
* @return
*/
private int lowerBorder(double d1) {
if(d4 < d1) double floor = Math.floor(d1);
d4 = -1; double d4 = floor + magic;
else
d4 = 0;
return (int) (floor - d4); if(d4 <= d1)
} d4 = 0;
else
d4 = 1;
return (int) (floor - d4);
}
/**
* Personal Rounding function to determine if a player is still touching a
* block or not
*
* @param d1
* @return
*/
private int upperBorder(double d1) {
double floor = Math.floor(d1);
double d4 = floor + magic2;
if(d4 < d1)
d4 = -1;
else
d4 = 0;
return (int) (floor - d4);
}
} }

View File

@ -20,102 +20,93 @@ import cc.co.evenprime.bukkit.nocheat.data.NukeData;
import cc.co.evenprime.bukkit.nocheat.data.PermissionData; import cc.co.evenprime.bukkit.nocheat.data.PermissionData;
import cc.co.evenprime.bukkit.nocheat.listeners.NukeBlockListener; import cc.co.evenprime.bukkit.nocheat.listeners.NukeBlockListener;
public class NukeCheck extends Check { public class NukeCheck extends Check {
private String kickMessage; private String kickMessage;
private String logMessage; private String logMessage;
private boolean limitReach;
public NukeCheck(NoCheat plugin, NoCheatConfiguration config) {
super(plugin, "nuke", PermissionData.PERMISSION_NUKE, config); private boolean limitReach;
} public NukeCheck(NoCheat plugin, NoCheatConfiguration config) {
@Override super(plugin, "nuke", PermissionData.PERMISSION_NUKE, config);
protected void configure(NoCheatConfiguration config) {
}
try {
kickMessage = config.getStringValue("nuke.kickmessage");
logMessage = config.getStringValue("nuke.logmessage").
replace("[player]", "%1$s");
limitReach = config.getBooleanValue("nuke.limitreach");
setActive(config.getBooleanValue("active.nuke"));
} catch (ConfigurationException e) {
setActive(false);
e.printStackTrace();
}
}
public void check(BlockBreakEvent event) { @Override
protected void configure(NoCheatConfiguration config) {
if(skipCheck(event.getPlayer())) { try {
return; kickMessage = config.getStringValue("nuke.kickmessage");
} logMessage = config.getStringValue("nuke.logmessage").replace("[player]", "%1$s");
NukeData data = plugin.getDataManager().getNukeData(event.getPlayer());
Block block = event.getBlock();
Location eyes = event.getPlayer().getEyeLocation(); limitReach = config.getBooleanValue("nuke.limitreach");
Vector direction = eyes.getDirection();
// Because it's not very precise on very short distances, setActive(config.getBooleanValue("active.nuke"));
// consider the length of the side of a block to be 2.0 instead of 1.0 } catch(ConfigurationException e) {
final double x1 = ((double)block.getX()) - eyes.getX() - 0.5; setActive(false);
final double y1 = ((double)block.getY()) - eyes.getY() - 0.5; e.printStackTrace();
final double z1 = ((double)block.getZ()) - eyes.getZ() - 0.5; }
}
final double x2 = x1 + 2; public void check(BlockBreakEvent event) {
final double y2 = y1 + 2;
final double z2 = z1 + 2;
double factor = new Vector(x1 + 1, y1 + 1, z1 + 1).length(); if(skipCheck(event.getPlayer())) {
return;
boolean tooFarAway = limitReach && factor > 4.85D; }
if(!tooFarAway && factor * direction.getX() >= x1 && factor * direction.getY() >= y1 && factor * direction.getZ() >= z1 &&
factor * direction.getX() <= x2 && factor * direction.getY() <= y2 && factor * direction.getZ() <= z2) {
if(data.counter > 0) {
data.counter--;
}
}
else {
data.counter++;
event.setCancelled(true);
if(data.counter > 10) {
String log = String.format(Locale.US, logMessage, event.getPlayer().getName());
plugin.log(Level.SEVERE, log);
event.getPlayer().kickPlayer(kickMessage);
data.counter = 0; // Reset to prevent problems on next login
}
}
NukeData data = plugin.getDataManager().getNukeData(event.getPlayer());
}
Block block = event.getBlock();
@Override Location eyes = event.getPlayer().getEyeLocation();
protected void registerListeners() { Vector direction = eyes.getDirection();
PluginManager pm = Bukkit.getServer().getPluginManager();
Listener blockListener = new NukeBlockListener(this); // Because it's not very precise on very short distances,
// consider the length of the side of a block to be 2.0 instead of 1.0
final double x1 = ((double) block.getX()) - eyes.getX() - 0.5;
final double y1 = ((double) block.getY()) - eyes.getY() - 0.5;
final double z1 = ((double) block.getZ()) - eyes.getZ() - 0.5;
// Register listeners for moving check final double x2 = x1 + 2;
pm.registerEvent(Event.Type.BLOCK_BREAK, blockListener, Priority.Lowest, plugin); final double y2 = y1 + 2;
pm.registerEvent(Event.Type.BLOCK_DAMAGE, blockListener, Priority.Monitor, plugin); final double z2 = z1 + 2;
double factor = new Vector(x1 + 1, y1 + 1, z1 + 1).length();
} boolean tooFarAway = limitReach && factor > 4.85D;
if(!tooFarAway && factor * direction.getX() >= x1 && factor * direction.getY() >= y1 && factor * direction.getZ() >= z1 && factor * direction.getX() <= x2 && factor * direction.getY() <= y2 && factor * direction.getZ() <= z2) {
if(data.counter > 0) {
data.counter--;
}
} else {
data.counter++;
event.setCancelled(true);
if(data.counter > 10) {
String log = String.format(Locale.US, logMessage, event.getPlayer().getName());
plugin.log(Level.SEVERE, log);
event.getPlayer().kickPlayer(kickMessage);
data.counter = 0; // Reset to prevent problems on next login
}
}
}
@Override
protected void registerListeners() {
PluginManager pm = Bukkit.getServer().getPluginManager();
Listener blockListener = new NukeBlockListener(this);
// Register listeners for moving check
pm.registerEvent(Event.Type.BLOCK_BREAK, blockListener, Priority.Lowest, plugin);
pm.registerEvent(Event.Type.BLOCK_DAMAGE, blockListener, Priority.Monitor, plugin);
}
} }

View File

@ -6,30 +6,27 @@ import cc.co.evenprime.bukkit.nocheat.data.MovingData;
public class RunningCheck { public class RunningCheck {
public RunningCheck() {}
public RunningCheck() { } public double check(final Location from, final Location to, final boolean isSneaking, final boolean isSwimming, final MovingData data, MovingCheck check) {
public double check(final Location from, final Location to, final boolean isSneaking, final boolean isSwimming, final MovingData data, MovingCheck check) { // How much further did the player move than expected??
double distanceAboveLimit = 0.0D;
// How much further did the player move than expected?? // First calculate the distance the player has moved horizontally
double distanceAboveLimit = 0.0D; final double xDistance = from.getX() - to.getX();
final double zDistance = from.getZ() - to.getZ();
// First calculate the distance the player has moved horizontally final double totalDistance = Math.sqrt((xDistance * xDistance + zDistance * zDistance));
final double xDistance = from.getX()-to.getX();
final double zDistance = from.getZ()-to.getZ();
final double totalDistance = Math.sqrt((xDistance*xDistance + zDistance*zDistance)); if(isSneaking) {
distanceAboveLimit = totalDistance - check.sneakWidth;
} else if(isSwimming) {
distanceAboveLimit = totalDistance - check.swimWidth;
} else {
distanceAboveLimit = totalDistance - check.stepWidth;
}
if(isSneaking) { return distanceAboveLimit - data.horizFreedom;
distanceAboveLimit = totalDistance - check.sneakWidth; }
}
else if(isSwimming) {
distanceAboveLimit = totalDistance - check.swimWidth;
}
else {
distanceAboveLimit = totalDistance - check.stepWidth;
}
return distanceAboveLimit - data.horizFreedom;
}
} }

View File

@ -22,180 +22,182 @@ import cc.co.evenprime.bukkit.nocheat.data.SpeedhackData;
import cc.co.evenprime.bukkit.nocheat.listeners.SpeedhackPlayerListener; import cc.co.evenprime.bukkit.nocheat.listeners.SpeedhackPlayerListener;
/** /**
* Log if a player sends to many move events in a specific time frame, usually the result of tinkering with the system clock * Log if a player sends to many move events in a specific time frame, usually
* the result of tinkering with the system clock
* *
* @author Evenprime * @author Evenprime
* *
*/ */
public class SpeedhackCheck extends Check { public class SpeedhackCheck extends Check {
public SpeedhackCheck(NoCheat plugin, NoCheatConfiguration config) { public SpeedhackCheck(NoCheat plugin, NoCheatConfiguration config) {
super(plugin, "speedhack", PermissionData.PERMISSION_SPEEDHACK, config); super(plugin, "speedhack", PermissionData.PERMISSION_SPEEDHACK, config);
} }
private static final int violationsLimit = 3; private static final int violationsLimit = 3;
// Limits for the speedhack check per second // Limits for the speedhack check per second
private int limits[]; private int limits[];
private String logMessage; private String logMessage;
// How should speedhack violations be treated? // How should speedhack violations be treated?
private Action actions[][]; private Action actions[][];
public void check(PlayerMoveEvent event) { public void check(PlayerMoveEvent event) {
Player player = event.getPlayer(); Player player = event.getPlayer();
// Should we check at all? // Should we check at all?
if(skipCheck(player)) return; if(skipCheck(player))
return;
// Ignore events of players in vehicles (these can be the cause of event spam between server and client) // Ignore events of players in vehicles (these can be the cause of event
// Ignore events if the player has positive y-Velocity (these can be the cause of event spam between server and client) // spam between server and client)
if(player.isInsideVehicle() || player.getVelocity().getY() > 0.0D) { // Ignore events if the player has positive y-Velocity (these can be the
return; // cause of event spam between server and client)
} if(player.isInsideVehicle() || player.getVelocity().getY() > 0.0D) {
return;
// During world transfers many events of same location get sent, ignore them all }
if(event.getFrom().equals(event.getTo())) {
return;
}
// Get the player-specific data // During world transfers many events of same location get sent, ignore
SpeedhackData data = plugin.getDataManager().getSpeedhackData(player); // them all
if(event.getFrom().equals(event.getTo())) {
return;
}
// Count the event (twice, to interpolate from 0.5 seconds to 1 second // Get the player-specific data
data.eventsSinceLastCheck += 2; SpeedhackData data = plugin.getDataManager().getSpeedhackData(player);
// Get the ticks of the server // Count the event (twice, to interpolate from 0.5 seconds to 1 second
int ticks = plugin.getServerTicks(); data.eventsSinceLastCheck += 2;
// Roughly half a second (= 10 ticks) passed // Get the ticks of the server
if(data.lastCheckTicks + 10 == ticks) { int ticks = plugin.getServerTicks();
// If we haven't already got a setback point, create one now // Roughly half a second (= 10 ticks) passed
if(data.setBackPoint == null) { if(data.lastCheckTicks + 10 == ticks) {
data.setBackPoint = event.getFrom();
}
if(plugin.getServerLag() > 150) { // If we haven't already got a setback point, create one now
// Any data would likely be unreliable with that lag if(data.setBackPoint == null) {
resetData(data, event.getFrom()); data.setBackPoint = event.getFrom();
} }
else {
int level = -1; if(plugin.getServerLag() > 150) {
// Any data would likely be unreliable with that lag
resetData(data, event.getFrom());
} else {
if(data.eventsSinceLastCheck > limits[2]) level = 2; int level = -1;
else if(data.eventsSinceLastCheck > limits[1]) level = 1;
else if(data.eventsSinceLastCheck > limits[0]) level = 0;
else {
resetData(data, event.getFrom());
}
if(level >= 0) { if(data.eventsSinceLastCheck > limits[2])
data.violationsInARowTotal++; level = 2;
} else if(data.eventsSinceLastCheck > limits[1])
level = 1;
else if(data.eventsSinceLastCheck > limits[0])
level = 0;
else {
resetData(data, event.getFrom());
}
if(data.violationsInARowTotal >= violationsLimit) { if(level >= 0) {
data.violationsInARow[level]++; data.violationsInARowTotal++;
action(actions[level], event, data.violationsInARow[level], data); }
}
// Reset value for next check if(data.violationsInARowTotal >= violationsLimit) {
data.eventsSinceLastCheck = 0; data.violationsInARow[level]++;
} action(actions[level], event, data.violationsInARow[level], data);
}
data.lastCheckTicks = ticks; // Reset value for next check
} data.eventsSinceLastCheck = 0;
else if(data.lastCheckTicks + 10 < ticks) }
{
// The player didn't move for the last 10 ticks
resetData(data, event.getFrom());
data.lastCheckTicks = ticks;
}
}
private static void resetData(SpeedhackData data, Location l) { data.lastCheckTicks = ticks;
data.violationsInARow[0] = 0; } else if(data.lastCheckTicks + 10 < ticks) {
data.violationsInARow[1] = 0; // The player didn't move for the last 10 ticks
data.violationsInARow[2] = 0; resetData(data, event.getFrom());
data.violationsInARowTotal = 0; data.lastCheckTicks = ticks;
data.eventsSinceLastCheck = 0; }
data.setBackPoint = l; }
}
private void action(Action actions[], PlayerMoveEvent event, int violations, SpeedhackData data) { private static void resetData(SpeedhackData data, Location l) {
data.violationsInARow[0] = 0;
data.violationsInARow[1] = 0;
data.violationsInARow[2] = 0;
data.violationsInARowTotal = 0;
data.eventsSinceLastCheck = 0;
data.setBackPoint = l;
}
if(actions == null) return; private void action(Action actions[], PlayerMoveEvent event, int violations, SpeedhackData data) {
for(Action a : actions) { if(actions == null)
if(a.firstAfter <= violations) { return;
if(a instanceof LogAction) {
String log = String.format(logMessage, event.getPlayer().getName(), data.eventsSinceLastCheck*2, limits[0]);
plugin.log(((LogAction)a).level, log);
}
else if(a.firstAfter == violations || a.repeat) {
if(a instanceof CancelAction) {
resetPlayer(event, data);
}
else if(a instanceof CustomAction) {
plugin.handleCustomAction((CustomAction)a, event.getPlayer());
}
}
}
}
}
private static void resetPlayer(PlayerMoveEvent event, SpeedhackData data) { for(Action a : actions) {
if(a.firstAfter <= violations) {
if(a instanceof LogAction) {
String log = String.format(logMessage, event.getPlayer().getName(), data.eventsSinceLastCheck * 2, limits[0]);
plugin.log(((LogAction) a).level, log);
} else if(a.firstAfter == violations || a.repeat) {
if(a instanceof CancelAction) {
resetPlayer(event, data);
} else if(a instanceof CustomAction) {
plugin.handleCustomAction((CustomAction) a, event.getPlayer());
}
}
}
}
}
if(data.setBackPoint == null) data.setBackPoint = event.getFrom(); private static void resetPlayer(PlayerMoveEvent event, SpeedhackData data) {
// If we have stored a location for the player, we put him back there if(data.setBackPoint == null)
event.setTo(data.setBackPoint); data.setBackPoint = event.getFrom();
}
@Override // If we have stored a location for the player, we put him back there
public void configure(NoCheatConfiguration config) { event.setTo(data.setBackPoint);
}
try { @Override
public void configure(NoCheatConfiguration config) {
limits = new int[3]; try {
limits[0] = config.getIntegerValue("speedhack.limits.low"); limits = new int[3];
limits[1] = config.getIntegerValue("speedhack.limits.med");
limits[2] = config.getIntegerValue("speedhack.limits.high");
logMessage = config.getStringValue("speedhack.logmessage"). limits[0] = config.getIntegerValue("speedhack.limits.low");
replace("[player]", "%1$s").replace("[events]", "%2$d").replace("[limit]", "%3$d"); limits[1] = config.getIntegerValue("speedhack.limits.med");
limits[2] = config.getIntegerValue("speedhack.limits.high");
actions = new Action[3][]; logMessage = config.getStringValue("speedhack.logmessage").replace("[player]", "%1$s").replace("[events]", "%2$d").replace("[limit]", "%3$d");
actions[0] = config.getActionValue("speedhack.action.low"); actions = new Action[3][];
actions[1] = config.getActionValue("speedhack.action.med");
actions[2] = config.getActionValue("speedhack.action.high");
setActive(config.getBooleanValue("active.speedhack")); actions[0] = config.getActionValue("speedhack.action.low");
} catch (ConfigurationException e) { actions[1] = config.getActionValue("speedhack.action.med");
setActive(false); actions[2] = config.getActionValue("speedhack.action.high");
e.printStackTrace();
}
}
setActive(config.getBooleanValue("active.speedhack"));
} catch(ConfigurationException e) {
setActive(false);
e.printStackTrace();
}
}
@Override
protected void registerListeners() {
PluginManager pm = Bukkit.getServer().getPluginManager();
@Override Listener speedhackPlayerListener = new SpeedhackPlayerListener(this);
protected void registerListeners() { // Register listeners for speedhack check
PluginManager pm = Bukkit.getServer().getPluginManager(); pm.registerEvent(Event.Type.PLAYER_MOVE, speedhackPlayerListener, Priority.High, plugin);
pm.registerEvent(Event.Type.PLAYER_TELEPORT, speedhackPlayerListener, Priority.Monitor, plugin);
Listener speedhackPlayerListener = new SpeedhackPlayerListener(this); }
// Register listeners for speedhack check
pm.registerEvent(Event.Type.PLAYER_MOVE, speedhackPlayerListener, Priority.High, plugin);
pm.registerEvent(Event.Type.PLAYER_TELEPORT, speedhackPlayerListener, Priority.Monitor, plugin);
} public void teleported(PlayerTeleportEvent event) {
SpeedhackData data = plugin.getDataManager().getSpeedhackData(event.getPlayer());
public void teleported(PlayerTeleportEvent event) { resetData(data, event.getTo());
SpeedhackData data = plugin.getDataManager().getSpeedhackData(event.getPlayer()); }
resetData(data, event.getTo());
}
} }

View File

@ -1,31 +1,30 @@
package cc.co.evenprime.bukkit.nocheat.config; package cc.co.evenprime.bukkit.nocheat.config;
public class BooleanOption extends ChildOption { public class BooleanOption extends ChildOption {
/** /**
* *
*/ */
private static final long serialVersionUID = 2258827414736580449L; private static final long serialVersionUID = 2258827414736580449L;
private boolean value; private boolean value;
public BooleanOption(String name, boolean initialValue) { public BooleanOption(String name, boolean initialValue) {
super(name); super(name);
this.value = initialValue; this.value = initialValue;
} }
public void setValue(boolean value) { public void setValue(boolean value) {
this.value = value; this.value = value;
} }
@Override @Override
public String getValue() { public String getValue() {
return Boolean.toString(value); return Boolean.toString(value);
} }
public boolean getBooleanValue() { public boolean getBooleanValue() {
return value; return value;
} }
} }

View File

@ -2,28 +2,26 @@ package cc.co.evenprime.bukkit.nocheat.config;
import cc.co.evenprime.bukkit.nocheat.wizard.gui.Explainations; import cc.co.evenprime.bukkit.nocheat.wizard.gui.Explainations;
public abstract class ChildOption extends Option { public abstract class ChildOption extends Option {
/** /**
* *
*/ */
private static final long serialVersionUID = -4648294833934457776L; private static final long serialVersionUID = -4648294833934457776L;
public ChildOption(String identifier) { public ChildOption(String identifier) {
super(identifier); super(identifier);
} }
public abstract String getValue();
public abstract String getValue(); @Override
public String toYAMLString(String prefix) {
return prefix + getIdentifier() + ": \"" + getValue() + "\"\r\n";
}
@Override @Override
public String toYAMLString(String prefix) { public String toDescriptionString(String prefix) {
return prefix + getIdentifier() + ": \"" + getValue() + "\"\r\n"; return prefix + getIdentifier() + ": \"" + Explainations.get(getFullIdentifier()).replace("\n", "\r\n" + prefix + "\t\t") + "\"\r\n";
} }
@Override
public String toDescriptionString(String prefix) {
return prefix + getIdentifier() + ": \"" + Explainations.get(getFullIdentifier()).replace("\n", "\r\n" + prefix + "\t\t") + "\"\r\n";
}
} }

View File

@ -4,83 +4,76 @@ import cc.co.evenprime.bukkit.nocheat.actions.CustomAction;
public class CustomActionOption extends ChildOption { public class CustomActionOption extends ChildOption {
private int firstAfter; private int firstAfter;
private boolean repeat; private boolean repeat;
private String command; private String command;
public CustomActionOption(String identifier, String command) {
public CustomActionOption(String identifier, String command) { super(identifier);
super(identifier); this.parseCommand(command);
}
this.parseCommand(command); private void parseCommand(String com) {
}
private void parseCommand(String com) { if(com.matches("\\[[0-9]*,[a-z]*\\] .*")) {
String s[] = com.split(" ", 2);
String s2[] = s[0].replace("[", "").replace("]", "").split(",");
firstAfter = Integer.parseInt(s2[0]);
repeat = Boolean.parseBoolean(s2[1]);
command = s[1];
} else if(com.matches("\\[[0-9]*\\] .*")) {
String s[] = com.split(" ", 2);
firstAfter = Integer.parseInt(s[0].replace("[", "").replace("]", ""));
repeat = true;
command = s[1];
} else {
firstAfter = 1;
repeat = true;
command = com;
}
}
if(com.matches("\\[[0-9]*,[a-z]*\\] .*")) { @Override
String s[] = com.split(" ", 2); public String getValue() {
String s2[] = s[0].replace("[", "").replace("]", "").split(","); if(firstAfter <= 1 && repeat) {
firstAfter = Integer.parseInt(s2[0]); return command;
repeat = Boolean.parseBoolean(s2[1]); } else if(repeat) {
command = s[1]; return "[" + firstAfter + "] " + command;
} } else {
else if(com.matches("\\[[0-9]*\\] .*")) { return "[" + firstAfter + "," + repeat + "] " + command;
String s[] = com.split(" ", 2); }
firstAfter = Integer.parseInt(s[0].replace("[", "").replace("]", "")); }
repeat = true;
command = s[1];
}
else
{
firstAfter = 1;
repeat = true;
command = com;
}
}
@Override public CustomAction getCustomActionValue() {
public String getValue() { return new CustomAction(firstAfter, repeat, command);
if(firstAfter <= 1 && repeat) { }
return command;
}
else if(repeat) {
return "["+firstAfter+"] "+ command;
}
else {
return "["+firstAfter+","+repeat+"] "+ command;
}
}
public String getCommandValue() {
return command;
}
public CustomAction getCustomActionValue() { public void setCommandValue(String command) {
return new CustomAction(firstAfter, repeat, command); this.command = command;
} }
public String getCommandValue() { public void setRepeatValue(boolean value) {
return command; this.repeat = value;
}
public void setCommandValue(String command) { }
this.command = command;
}
public void setRepeatValue(boolean value) { public boolean getRepeatValue() {
this.repeat = value; return repeat;
}
} public int getFirstAfterValue() {
return firstAfter;
}
public boolean getRepeatValue() { public void setFirsttAfterValue(int value) {
return repeat; this.firstAfter = value;
}
public int getFirstAfterValue() { }
return firstAfter;
}
public void setFirsttAfterValue(int value) {
this.firstAfter = value;
}
} }

View File

@ -1,33 +1,32 @@
package cc.co.evenprime.bukkit.nocheat.config; package cc.co.evenprime.bukkit.nocheat.config;
public class IntegerOption extends TextFieldOption { public class IntegerOption extends TextFieldOption {
/** /**
* *
*/ */
private static final long serialVersionUID = 2258827414736580449L; private static final long serialVersionUID = 2258827414736580449L;
public IntegerOption(String name, int initialValue) {
super(name, String.valueOf(initialValue), 5);
}
@Override public IntegerOption(String name, int initialValue) {
public boolean isValid(String value) {
if(!super.isValid(value)) return false;
try {
Integer.parseInt(value);
return true;
}
catch(Exception e) {
return false;
}
}
public int getIntegerValue() { super(name, String.valueOf(initialValue), 5);
return Integer.parseInt(this.getValue()); }
}
@Override
public boolean isValid(String value) {
if(!super.isValid(value))
return false;
try {
Integer.parseInt(value);
return true;
} catch(Exception e) {
return false;
}
}
public int getIntegerValue() {
return Integer.parseInt(this.getValue());
}
} }

View File

@ -2,81 +2,77 @@ package cc.co.evenprime.bukkit.nocheat.config;
import java.util.logging.Level; import java.util.logging.Level;
public class LevelOption extends ChildOption { public class LevelOption extends ChildOption {
/** /**
* *
*/ */
private static final long serialVersionUID = -1609308017422576285L; private static final long serialVersionUID = -1609308017422576285L;
private LogLevel option; private LogLevel option;
public enum LogLevel { public enum LogLevel {
OFF("off", "never", Level.OFF), LOW("low", "all messages", Level.INFO), MED("med", "important messages", Level.WARNING), HIGH("high", "very important messages", Level.SEVERE);
OFF("off", "never", Level.OFF), private final String value;
LOW("low", "all messages", Level.INFO), private final String description;
MED("med", "important messages", Level.WARNING), private final Level level;
HIGH("high", "very important messages", Level.SEVERE);
private final String value; private LogLevel(String value, String description, Level level) {
private final String description; this.value = value;
private final Level level; this.description = description;
this.level = level;
}
private LogLevel(String value, String description, Level level) { public String asString() {
this.value = value; return this.value;
this.description = description; }
this.level = level;
}
public String asString() { return this.value; } public static LogLevel getLogLevelFromString(String s) {
if(s == null)
return OFF;
if("off".equals(s))
return OFF;
else if("low".equals(s))
return LOW;
else if("med".equals(s))
return MED;
else if("high".equals(s))
return HIGH;
else
return OFF;
}
public static LogLevel getLogLevelFromString(String s) { public String toString() {
if(s == null) return OFF; return this.name() + ": " + description;
if("off".equals(s)) }
return OFF;
else if("low".equals(s))
return LOW;
else if("med".equals(s))
return MED;
else if("high".equals(s))
return HIGH;
else
return OFF;
}
public Level getLevel() {
return level;
}
}
public String toString() { public LevelOption(String identifier, LogLevel initialValue) {
return this.name() + ": " + description;
}
public Level getLevel() { super(identifier);
return level; this.option = initialValue;
} }
}
public LevelOption(String identifier, LogLevel initialValue) { @Override
public String getValue() {
return option.asString();
}
super(identifier); public void setValue(LogLevel value) {
this.option = initialValue; this.option = value;
} }
public LogLevel getOptionValue() {
return this.option;
}
@Override public Level getLevelValue() {
public String getValue() { return this.option.getLevel();
return option.asString(); }
}
public void setValue(LogLevel value) {
this.option = value;
}
public LogLevel getOptionValue() {
return this.option;
}
public Level getLevelValue() {
return this.option.getLevel();
}
} }

View File

@ -2,12 +2,12 @@ package cc.co.evenprime.bukkit.nocheat.config;
public class LongStringOption extends TextFieldOption { public class LongStringOption extends TextFieldOption {
/** /**
* *
*/ */
private static final long serialVersionUID = 2258827414736580449L; private static final long serialVersionUID = 2258827414736580449L;
public LongStringOption(String name, String initialValue) { public LongStringOption(String name, String initialValue) {
super(name, initialValue, 60); super(name, initialValue, 60);
} }
} }

View File

@ -2,12 +2,12 @@ package cc.co.evenprime.bukkit.nocheat.config;
public class MediumStringOption extends TextFieldOption { public class MediumStringOption extends TextFieldOption {
/** /**
* *
*/ */
private static final long serialVersionUID = 2258827414736580449L; private static final long serialVersionUID = 2258827414736580449L;
public MediumStringOption(String name, String initialValue) { public MediumStringOption(String name, String initialValue) {
super(name, initialValue, 30); super(name, initialValue, 30);
} }
} }

View File

@ -25,455 +25,406 @@ import cc.co.evenprime.bukkit.nocheat.yaml.SimpleYaml;
* Central location for everything that's described in the configuration file * Central location for everything that's described in the configuration file
* *
* @author Evenprime * @author Evenprime
* *
*/ */
public class NoCheatConfiguration { public class NoCheatConfiguration {
public final static String configFile = "plugins/NoCheat/nocheat.yml";
public final static String descriptionsFile = "plugins/NoCheat/descriptions.txt";
public final static String configFile = "plugins/NoCheat/nocheat.yml"; private ParentOption root;
public final static String descriptionsFile = "plugins/NoCheat/descriptions.txt";
private ParentOption root; private final Map<String, Action> actionMap = new HashMap<String, Action>();
private final Map<String, Action> actionMap = new HashMap<String,Action>(); private Map<String, Object> yamlContent = new HashMap<String, Object>();
private Map<String, Object> yamlContent = new HashMap<String, Object>(); // Our personal logger
private final static String loggerName = "cc.co.evenprime.nocheat";
public final Logger logger = Logger.getLogger(loggerName);
// Our personal logger // Our log output to a file
private final static String loggerName = "cc.co.evenprime.nocheat"; private FileHandler fh = null;
public final Logger logger = Logger.getLogger(loggerName);
// Our log output to a file public NoCheatConfiguration(File configurationFile, File descriptionsFile) {
private FileHandler fh = null;
public NoCheatConfiguration(File configurationFile, File descriptionsFile) {
// Setup the configuration tree
config(configurationFile, descriptionsFile);
}
/**
* Read the configuration file and assign either standard values or whatever is declared in the file
* @param configurationFile
*/
public void config(File configurationFile, File descriptionsFile) {
try {
yamlContent = (Map<String, Object>) SimpleYaml.read(configurationFile);
} catch (Exception e) {
System.out.println("Couldn't use existing nocheat.yml, creating a new file.");
yamlContent = new HashMap<String, Object>();
}
root = new ParentOption("", false);
/*** LOGGING section ***/
{
ParentOption loggingNode = new ParentOption("logging", false);
root.add(loggingNode);
loggingNode.add(new MediumStringOption("filename",
SimpleYaml.getString("logging.filename", "plugins/NoCheat/nocheat.log", yamlContent)));
loggingNode.add(new LevelOption("logtofile",
LogLevel.getLogLevelFromString(SimpleYaml.getString("logging.logtofile", LogLevel.LOW.asString(), yamlContent))));
loggingNode.add(new LevelOption("logtoconsole",
LogLevel.getLogLevelFromString(SimpleYaml.getString("logging.logtoconsole", LogLevel.HIGH.asString(), yamlContent))));
loggingNode.add(new LevelOption("logtochat",
LogLevel.getLogLevelFromString(SimpleYaml.getString("logging.logtochat", LogLevel.MED.asString(), yamlContent))));
loggingNode.add(new LevelOption("logtoirc",
LogLevel.getLogLevelFromString(SimpleYaml.getString("logging.logtoirc", LogLevel.MED.asString(), yamlContent))));
loggingNode.add(new ShortStringOption("logtoirctag",
SimpleYaml.getString("logging.logtoirctag", "nocheat", yamlContent)));
}
root.add(new BooleanOption("newpermsystem", SimpleYaml.getBoolean("newpermsystem", false, yamlContent)));
root.add(new BooleanOption("showinfomessages", SimpleYaml.getBoolean("showinfomessages", true, yamlContent)));
/*** ACTIVE section ***/
{
ParentOption activeNode = new ParentOption("active", false);
root.add(activeNode);
activeNode.add(new BooleanOption("speedhack",
SimpleYaml.getBoolean("active.speedhack", true, yamlContent)));
activeNode.add(new BooleanOption("moving",
SimpleYaml.getBoolean("active.moving", true, yamlContent)));
activeNode.add(new BooleanOption("airbuild",
SimpleYaml.getBoolean("active.airbuild", false, yamlContent)));
activeNode.add(new BooleanOption("bogusitems",
SimpleYaml.getBoolean("active.bogusitems", false, yamlContent)));
activeNode.add(new BooleanOption("nuke",
SimpleYaml.getBoolean("active.nuke", false, yamlContent)));
}
/*** SPEEDHACK section ***/
{
ParentOption speedhackNode = new ParentOption("speedhack", false);
root.add(speedhackNode);
speedhackNode.add(new LongStringOption("logmessage",
SimpleYaml.getString("speedhack.logmessage", "[player] sent [events] move events, but only [limit] were allowed. Speedhack?", yamlContent)));
speedhackNode.add(new BooleanOption("checkops",
SimpleYaml.getBoolean("speedhack.checkops", false, yamlContent)));
/*** SPEEDHACK LIMITS section ***/
{
ParentOption speedhackLimitsNode = new ParentOption("limits", false);
speedhackNode.add(speedhackLimitsNode);
speedhackLimitsNode.add(new IntegerOption("low",
SimpleYaml.getInt("speedhack.limits.low", 22, yamlContent)));
speedhackLimitsNode.add(new IntegerOption("med",
SimpleYaml.getInt("speedhack.limits.med", 33, yamlContent)));
speedhackLimitsNode.add(new IntegerOption("high",
SimpleYaml.getInt("speedhack.limits.high", 44, yamlContent)));
}
/*** SPEEDHACK ACTIONS section ***/
{
ParentOption speedhackActionNode = new ParentOption("action", false);
speedhackNode.add(speedhackActionNode);
speedhackActionNode.add(new MediumStringOption("low",
SimpleYaml.getString("speedhack.action.low", "loglow cancel", yamlContent)));
speedhackActionNode.add(new MediumStringOption("med",
SimpleYaml.getString("speedhack.action.med", "logmed cancel", yamlContent)));
speedhackActionNode.add(new MediumStringOption("high",
SimpleYaml.getString("speedhack.action.high", "loghigh cancel", yamlContent)));
}
}
/*** MOVING section ***/
{
ParentOption movingNode = new ParentOption("moving", false);
root.add(movingNode);
movingNode.add(new LongStringOption("logmessage",
SimpleYaml.getString("moving.logmessage", "Moving violation: [player] from [world] [from] to [to] distance [distance]", yamlContent)));
movingNode.add(new LongStringOption("summarymessage",
SimpleYaml.getString("moving.summarymessage", "Moving summary of last ~[timeframe] seconds: [player] total Violations: [violations]", yamlContent)));
movingNode.add(new IntegerOption("summaryafter",
SimpleYaml.getInt("moving.summaryafter", 15, yamlContent)));
movingNode.add(new BooleanOption("allowflying",
SimpleYaml.getBoolean("moving.allowflying", false, yamlContent)));
movingNode.add(new BooleanOption("allowfakesneak",
SimpleYaml.getBoolean("moving.allowfakesneak", true, yamlContent)));
movingNode.add(new BooleanOption("allowfastswim",
SimpleYaml.getBoolean("moving.allowfastswim", false, yamlContent)));
movingNode.add(new BooleanOption("waterelevators",
SimpleYaml.getBoolean("moving.waterelevators", false, yamlContent)));
movingNode.add(new BooleanOption("checkops",
SimpleYaml.getBoolean("moving.checkops", false, yamlContent)));
movingNode.add(new BooleanOption("enforceteleport",
SimpleYaml.getBoolean("moving.enforceteleport", false, yamlContent)));
/*** MOVING LIMITS section ***/
{
ParentOption movingLimitsNode = new ParentOption("limits", false);
movingNode.add(movingLimitsNode);
movingLimitsNode.add(new IntegerOption("walking",
SimpleYaml.getInt("moving.limits.walking", 22, yamlContent)));
movingLimitsNode.add(new IntegerOption("sneaking",
SimpleYaml.getInt("moving.limits.sneaking", 14, yamlContent)));
movingLimitsNode.add(new IntegerOption("swimming",
SimpleYaml.getInt("moving.limits.swimming", 18, yamlContent)));
}
/*** MOVING ACTION section ***/
{
ParentOption movingActionNode = new ParentOption("action", false);
movingNode.add(movingActionNode);
movingActionNode.add(new MediumStringOption("low",
SimpleYaml.getString("moving.action.low", "loglow cancel", yamlContent)));
movingActionNode.add(new MediumStringOption("med",
SimpleYaml.getString("moving.action.med", "logmed cancel", yamlContent)));
movingActionNode.add(new MediumStringOption("high",
SimpleYaml.getString("moving.action.high", "loghigh cancel", yamlContent)));
}
}
/*** AIRBUILD section ***/
{
ParentOption airbuildNode = new ParentOption("airbuild", false);
root.add(airbuildNode);
airbuildNode.add(new BooleanOption("checkops",
SimpleYaml.getBoolean("airbuild.checkops", false, yamlContent)));
/*** AIRBUILD LIMITS section ***/
{
ParentOption airbuildLimitsNode = new ParentOption("limits", false);
airbuildNode.add(airbuildLimitsNode);
airbuildLimitsNode.add(new IntegerOption("low",
SimpleYaml.getInt("airbuild.limits.low", 1, yamlContent)));
airbuildLimitsNode.add(new IntegerOption("med",
SimpleYaml.getInt("airbuild.limits.med", 3, yamlContent)));
airbuildLimitsNode.add(new IntegerOption("high",
SimpleYaml.getInt("airbuild.limits.high", 10, yamlContent)));
}
/*** AIRBUILD ACTION section ***/
{
ParentOption airbuildActionNode = new ParentOption("action", false);
airbuildNode.add(airbuildActionNode);
airbuildActionNode.add(new MediumStringOption("low",
SimpleYaml.getString("airbuild.action.low", "loglow cancel", yamlContent)));
airbuildActionNode.add(new MediumStringOption("med",
SimpleYaml.getString("airbuild.action.med", "logmed cancel", yamlContent)));
airbuildActionNode.add(new MediumStringOption("high",
SimpleYaml.getString("airbuild.action.high", "loghigh cancel", yamlContent)));
}
}
/*** BOGUSITEMS section ***/
{
ParentOption bogusitemsNode = new ParentOption("bogusitems", false);
root.add(bogusitemsNode);
bogusitemsNode.add(new BooleanOption("checkops",
SimpleYaml.getBoolean("bogusitems.checkops", false, yamlContent)));
}
/*** NUKE section ***/
{
ParentOption nukeNode = new ParentOption("nuke", false);
root.add(nukeNode);
nukeNode.add(new BooleanOption("checkops",
SimpleYaml.getBoolean("nuke.checkops", false, yamlContent)));
nukeNode.add(new LongStringOption("logmessage",
SimpleYaml.getString("nuke.logmessage", "Nuke: [player] tried to nuke the world", yamlContent)));
nukeNode.add(new LongStringOption("kickmessage",
SimpleYaml.getString("nuke.kickmessage", "No nuking allowed", yamlContent)));
nukeNode.add(new BooleanOption("limitreach",
SimpleYaml.getBoolean("nuke.limitreach", true, yamlContent)));
}
/*** CUSTOMACTIONS section ***/
{
ParentOption customActionsNode = new ParentOption("customactions", true);
root.add(customActionsNode);
Set<String> customs = SimpleYaml.getKeys("customactions", yamlContent);
for(String s : customs) {
CustomActionOption o = new CustomActionOption(s, SimpleYaml.getString("customactions."+s, "unknown", yamlContent));
customActionsNode.add(o);
actionMap.put(s, o.getCustomActionValue());
}
}
writeConfigFile(configurationFile, this);
writeDescriptionFile(descriptionsFile, this);
}
public void setupFileLogger() {
logger.setLevel(Level.INFO);
logger.setUseParentHandlers(false);
if(fh == null) {
try {
fh = new FileHandler(getStringValue("logging.filename"), true);
fh.setLevel(getLogLevelValue("logging.logtofile"));
fh.setFormatter(new LogFileFormatter());
logger.addHandler(fh);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void cleanup() {
if(fh != null) {
try {
logger.removeHandler(fh);
fh.flush();
fh.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private Action[] stringToActions(String string) {
List<Action> as = new LinkedList<Action>();
String[] parts = string.split(" ");
for(String s : parts) {
if(s.equals("loglow"))
as.add(LogAction.loglow);
else if(s.equals("logmed"))
as.add(LogAction.logmed);
else if(s.equals("loghigh"))
as.add(LogAction.loghigh);
else if(s.equals("cancel"))
as.add(CancelAction.cancel);
else if(actionMap.get(s) != null)
as.add(actionMap.get(s));
else
{
System.out.println("NC: Couldn't parse custom action '" + s + "'");
}
}
return as.toArray(new Action[as.size()]);
}
/**
* Write configuration file to specific filename
* @param f
*/
public static void writeConfigFile(File f, NoCheatConfiguration configuration) {
try {
if(f.getParentFile() != null)
f.getParentFile().mkdirs();
f.createNewFile();
BufferedWriter w = new BufferedWriter(new FileWriter(f));
w.write(configuration.getRoot().toYAMLString(""));
w.flush(); w.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Write a file with the descriptions of all options
* @param f
*/
private static void writeDescriptionFile(File f, NoCheatConfiguration configuration) {
try {
if(f.getParentFile() != null)
f.getParentFile().mkdirs();
f.createNewFile();
BufferedWriter w = new BufferedWriter(new FileWriter(f));
w.write(configuration.getRoot().toDescriptionString(""));
w.flush(); w.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public Action[] getActionValue(String optionName) throws ConfigurationException {
return stringToActions(getStringOption(optionName).getValue());
}
public int getIntegerValue(String optionName) throws ConfigurationException {
return getIntegerOption(optionName).getIntegerValue();
}
private IntegerOption getIntegerOption(String optionName) throws ConfigurationException {
Option o = getOption(optionName) ;
if(o instanceof IntegerOption) {
return (IntegerOption)o;
}
throw new ConfigurationException("Config Node " + optionName + " is not an integer");
}
public String getStringValue(String optionName) throws ConfigurationException {
return getStringOption(optionName).getValue();
}
private TextFieldOption getStringOption(String optionName) throws ConfigurationException {
Option o = getOption(optionName);
if(o instanceof TextFieldOption) {
return (TextFieldOption)o;
}
throw new ConfigurationException("Config Node " + optionName + " is not a string");
}
public Level getLogLevelValue(String optionName) throws ConfigurationException {
return getLogLevelOption(optionName).getLevelValue();
}
private LevelOption getLogLevelOption(String optionName) throws ConfigurationException {
Option o = getOption(optionName);
if(o instanceof LevelOption) {
return (LevelOption)o;
}
throw new ConfigurationException("Config Node " + optionName + " is not a loglevel");
}
public boolean getBooleanValue(String optionName) throws ConfigurationException {
return getBooleanOption(optionName).getBooleanValue();
}
private BooleanOption getBooleanOption(String optionName) throws ConfigurationException {
Option o = getOption(optionName);
if(o instanceof BooleanOption) {
return (BooleanOption)o;
}
throw new ConfigurationException("Config Node " + optionName + " is not a boolean");
}
private Option getOption(String optionName) throws ConfigurationException {
LinkedList<String> l = new LinkedList<String>();
for(String s : optionName.split("\\.")) {
l.addLast(s);
}
return getOption(root, l);
}
private Option getOption(Option parent, LinkedList<String> names) throws ConfigurationException { // Setup the configuration tree
config(configurationFile, descriptionsFile);
if(names.size() == 0) {
return parent;
}
else if(parent instanceof ParentOption) {
for(Option o2 : ((ParentOption)parent).getChildOptions()) {
if(o2.getIdentifier().equals(names.getFirst())) {
names.removeFirst();
return getOption(o2, names);
}
}
}
throw new ConfigurationException("Config Node doesn't exist"); }
}
public ParentOption getRoot() { /**
return root; * Read the configuration file and assign either standard values or whatever
} * is declared in the file
*
* @param configurationFile
*/
public void config(File configurationFile, File descriptionsFile) {
try {
yamlContent = (Map<String, Object>) SimpleYaml.read(configurationFile);
} catch(Exception e) {
System.out.println("Couldn't use existing nocheat.yml, creating a new file.");
yamlContent = new HashMap<String, Object>();
}
root = new ParentOption("", false);
/*** LOGGING section ***/
{
ParentOption loggingNode = new ParentOption("logging", false);
root.add(loggingNode);
loggingNode.add(new MediumStringOption("filename", SimpleYaml.getString("logging.filename", "plugins/NoCheat/nocheat.log", yamlContent)));
loggingNode.add(new LevelOption("logtofile", LogLevel.getLogLevelFromString(SimpleYaml.getString("logging.logtofile", LogLevel.LOW.asString(), yamlContent))));
loggingNode.add(new LevelOption("logtoconsole", LogLevel.getLogLevelFromString(SimpleYaml.getString("logging.logtoconsole", LogLevel.HIGH.asString(), yamlContent))));
loggingNode.add(new LevelOption("logtochat", LogLevel.getLogLevelFromString(SimpleYaml.getString("logging.logtochat", LogLevel.MED.asString(), yamlContent))));
loggingNode.add(new LevelOption("logtoirc", LogLevel.getLogLevelFromString(SimpleYaml.getString("logging.logtoirc", LogLevel.MED.asString(), yamlContent))));
loggingNode.add(new ShortStringOption("logtoirctag", SimpleYaml.getString("logging.logtoirctag", "nocheat", yamlContent)));
}
root.add(new BooleanOption("newpermsystem", SimpleYaml.getBoolean("newpermsystem", false, yamlContent)));
root.add(new BooleanOption("showinfomessages", SimpleYaml.getBoolean("showinfomessages", true, yamlContent)));
/*** ACTIVE section ***/
{
ParentOption activeNode = new ParentOption("active", false);
root.add(activeNode);
activeNode.add(new BooleanOption("speedhack", SimpleYaml.getBoolean("active.speedhack", true, yamlContent)));
activeNode.add(new BooleanOption("moving", SimpleYaml.getBoolean("active.moving", true, yamlContent)));
activeNode.add(new BooleanOption("airbuild", SimpleYaml.getBoolean("active.airbuild", false, yamlContent)));
activeNode.add(new BooleanOption("bogusitems", SimpleYaml.getBoolean("active.bogusitems", false, yamlContent)));
activeNode.add(new BooleanOption("nuke", SimpleYaml.getBoolean("active.nuke", false, yamlContent)));
}
/*** SPEEDHACK section ***/
{
ParentOption speedhackNode = new ParentOption("speedhack", false);
root.add(speedhackNode);
speedhackNode.add(new LongStringOption("logmessage", SimpleYaml.getString("speedhack.logmessage", "[player] sent [events] move events, but only [limit] were allowed. Speedhack?", yamlContent)));
speedhackNode.add(new BooleanOption("checkops", SimpleYaml.getBoolean("speedhack.checkops", false, yamlContent)));
/*** SPEEDHACK LIMITS section ***/
{
ParentOption speedhackLimitsNode = new ParentOption("limits", false);
speedhackNode.add(speedhackLimitsNode);
speedhackLimitsNode.add(new IntegerOption("low", SimpleYaml.getInt("speedhack.limits.low", 22, yamlContent)));
speedhackLimitsNode.add(new IntegerOption("med", SimpleYaml.getInt("speedhack.limits.med", 33, yamlContent)));
speedhackLimitsNode.add(new IntegerOption("high", SimpleYaml.getInt("speedhack.limits.high", 44, yamlContent)));
}
/*** SPEEDHACK ACTIONS section ***/
{
ParentOption speedhackActionNode = new ParentOption("action", false);
speedhackNode.add(speedhackActionNode);
speedhackActionNode.add(new MediumStringOption("low", SimpleYaml.getString("speedhack.action.low", "loglow cancel", yamlContent)));
speedhackActionNode.add(new MediumStringOption("med", SimpleYaml.getString("speedhack.action.med", "logmed cancel", yamlContent)));
speedhackActionNode.add(new MediumStringOption("high", SimpleYaml.getString("speedhack.action.high", "loghigh cancel", yamlContent)));
}
}
/*** MOVING section ***/
{
ParentOption movingNode = new ParentOption("moving", false);
root.add(movingNode);
movingNode.add(new LongStringOption("logmessage", SimpleYaml.getString("moving.logmessage", "Moving violation: [player] from [world] [from] to [to] distance [distance]", yamlContent)));
movingNode.add(new LongStringOption("summarymessage", SimpleYaml.getString("moving.summarymessage", "Moving summary of last ~[timeframe] seconds: [player] total Violations: [violations]", yamlContent)));
movingNode.add(new IntegerOption("summaryafter", SimpleYaml.getInt("moving.summaryafter", 15, yamlContent)));
movingNode.add(new BooleanOption("allowflying", SimpleYaml.getBoolean("moving.allowflying", false, yamlContent)));
movingNode.add(new BooleanOption("allowfakesneak", SimpleYaml.getBoolean("moving.allowfakesneak", true, yamlContent)));
movingNode.add(new BooleanOption("allowfastswim", SimpleYaml.getBoolean("moving.allowfastswim", false, yamlContent)));
movingNode.add(new BooleanOption("waterelevators", SimpleYaml.getBoolean("moving.waterelevators", false, yamlContent)));
movingNode.add(new BooleanOption("checkops", SimpleYaml.getBoolean("moving.checkops", false, yamlContent)));
movingNode.add(new BooleanOption("enforceteleport", SimpleYaml.getBoolean("moving.enforceteleport", false, yamlContent)));
/*** MOVING LIMITS section ***/
{
ParentOption movingLimitsNode = new ParentOption("limits", false);
movingNode.add(movingLimitsNode);
movingLimitsNode.add(new IntegerOption("walking", SimpleYaml.getInt("moving.limits.walking", 22, yamlContent)));
movingLimitsNode.add(new IntegerOption("sneaking", SimpleYaml.getInt("moving.limits.sneaking", 14, yamlContent)));
movingLimitsNode.add(new IntegerOption("swimming", SimpleYaml.getInt("moving.limits.swimming", 18, yamlContent)));
}
/*** MOVING ACTION section ***/
{
ParentOption movingActionNode = new ParentOption("action", false);
movingNode.add(movingActionNode);
movingActionNode.add(new MediumStringOption("low", SimpleYaml.getString("moving.action.low", "loglow cancel", yamlContent)));
movingActionNode.add(new MediumStringOption("med", SimpleYaml.getString("moving.action.med", "logmed cancel", yamlContent)));
movingActionNode.add(new MediumStringOption("high", SimpleYaml.getString("moving.action.high", "loghigh cancel", yamlContent)));
}
}
/*** AIRBUILD section ***/
{
ParentOption airbuildNode = new ParentOption("airbuild", false);
root.add(airbuildNode);
airbuildNode.add(new BooleanOption("checkops", SimpleYaml.getBoolean("airbuild.checkops", false, yamlContent)));
/*** AIRBUILD LIMITS section ***/
{
ParentOption airbuildLimitsNode = new ParentOption("limits", false);
airbuildNode.add(airbuildLimitsNode);
airbuildLimitsNode.add(new IntegerOption("low", SimpleYaml.getInt("airbuild.limits.low", 1, yamlContent)));
airbuildLimitsNode.add(new IntegerOption("med", SimpleYaml.getInt("airbuild.limits.med", 3, yamlContent)));
airbuildLimitsNode.add(new IntegerOption("high", SimpleYaml.getInt("airbuild.limits.high", 10, yamlContent)));
}
/*** AIRBUILD ACTION section ***/
{
ParentOption airbuildActionNode = new ParentOption("action", false);
airbuildNode.add(airbuildActionNode);
airbuildActionNode.add(new MediumStringOption("low", SimpleYaml.getString("airbuild.action.low", "loglow cancel", yamlContent)));
airbuildActionNode.add(new MediumStringOption("med", SimpleYaml.getString("airbuild.action.med", "logmed cancel", yamlContent)));
airbuildActionNode.add(new MediumStringOption("high", SimpleYaml.getString("airbuild.action.high", "loghigh cancel", yamlContent)));
}
}
/*** BOGUSITEMS section ***/
{
ParentOption bogusitemsNode = new ParentOption("bogusitems", false);
root.add(bogusitemsNode);
bogusitemsNode.add(new BooleanOption("checkops", SimpleYaml.getBoolean("bogusitems.checkops", false, yamlContent)));
}
/*** NUKE section ***/
{
ParentOption nukeNode = new ParentOption("nuke", false);
root.add(nukeNode);
nukeNode.add(new BooleanOption("checkops", SimpleYaml.getBoolean("nuke.checkops", false, yamlContent)));
nukeNode.add(new LongStringOption("logmessage", SimpleYaml.getString("nuke.logmessage", "Nuke: [player] tried to nuke the world", yamlContent)));
nukeNode.add(new LongStringOption("kickmessage", SimpleYaml.getString("nuke.kickmessage", "No nuking allowed", yamlContent)));
nukeNode.add(new BooleanOption("limitreach", SimpleYaml.getBoolean("nuke.limitreach", true, yamlContent)));
}
/*** CUSTOMACTIONS section ***/
{
ParentOption customActionsNode = new ParentOption("customactions", true);
root.add(customActionsNode);
Set<String> customs = SimpleYaml.getKeys("customactions", yamlContent);
for(String s : customs) {
CustomActionOption o = new CustomActionOption(s, SimpleYaml.getString("customactions." + s, "unknown", yamlContent));
customActionsNode.add(o);
actionMap.put(s, o.getCustomActionValue());
}
}
writeConfigFile(configurationFile, this);
writeDescriptionFile(descriptionsFile, this);
}
public void setupFileLogger() {
logger.setLevel(Level.INFO);
logger.setUseParentHandlers(false);
if(fh == null) {
try {
fh = new FileHandler(getStringValue("logging.filename"), true);
fh.setLevel(getLogLevelValue("logging.logtofile"));
fh.setFormatter(new LogFileFormatter());
logger.addHandler(fh);
} catch(Exception e) {
e.printStackTrace();
}
}
}
public void cleanup() {
if(fh != null) {
try {
logger.removeHandler(fh);
fh.flush();
fh.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
private Action[] stringToActions(String string) {
List<Action> as = new LinkedList<Action>();
String[] parts = string.split(" ");
for(String s : parts) {
if(s.equals("loglow"))
as.add(LogAction.loglow);
else if(s.equals("logmed"))
as.add(LogAction.logmed);
else if(s.equals("loghigh"))
as.add(LogAction.loghigh);
else if(s.equals("cancel"))
as.add(CancelAction.cancel);
else if(actionMap.get(s) != null)
as.add(actionMap.get(s));
else {
System.out.println("NC: Couldn't parse custom action '" + s + "'");
}
}
return as.toArray(new Action[as.size()]);
}
/**
* Write configuration file to specific filename
*
* @param f
*/
public static void writeConfigFile(File f, NoCheatConfiguration configuration) {
try {
if(f.getParentFile() != null)
f.getParentFile().mkdirs();
f.createNewFile();
BufferedWriter w = new BufferedWriter(new FileWriter(f));
w.write(configuration.getRoot().toYAMLString(""));
w.flush();
w.close();
} catch(IOException e) {
e.printStackTrace();
}
}
/**
* Write a file with the descriptions of all options
*
* @param f
*/
private static void writeDescriptionFile(File f, NoCheatConfiguration configuration) {
try {
if(f.getParentFile() != null)
f.getParentFile().mkdirs();
f.createNewFile();
BufferedWriter w = new BufferedWriter(new FileWriter(f));
w.write(configuration.getRoot().toDescriptionString(""));
w.flush();
w.close();
} catch(IOException e) {
e.printStackTrace();
}
}
public Action[] getActionValue(String optionName) throws ConfigurationException {
return stringToActions(getStringOption(optionName).getValue());
}
public int getIntegerValue(String optionName) throws ConfigurationException {
return getIntegerOption(optionName).getIntegerValue();
}
private IntegerOption getIntegerOption(String optionName) throws ConfigurationException {
Option o = getOption(optionName);
if(o instanceof IntegerOption) {
return (IntegerOption) o;
}
throw new ConfigurationException("Config Node " + optionName + " is not an integer");
}
public String getStringValue(String optionName) throws ConfigurationException {
return getStringOption(optionName).getValue();
}
private TextFieldOption getStringOption(String optionName) throws ConfigurationException {
Option o = getOption(optionName);
if(o instanceof TextFieldOption) {
return (TextFieldOption) o;
}
throw new ConfigurationException("Config Node " + optionName + " is not a string");
}
public Level getLogLevelValue(String optionName) throws ConfigurationException {
return getLogLevelOption(optionName).getLevelValue();
}
private LevelOption getLogLevelOption(String optionName) throws ConfigurationException {
Option o = getOption(optionName);
if(o instanceof LevelOption) {
return (LevelOption) o;
}
throw new ConfigurationException("Config Node " + optionName + " is not a loglevel");
}
public boolean getBooleanValue(String optionName) throws ConfigurationException {
return getBooleanOption(optionName).getBooleanValue();
}
private BooleanOption getBooleanOption(String optionName) throws ConfigurationException {
Option o = getOption(optionName);
if(o instanceof BooleanOption) {
return (BooleanOption) o;
}
throw new ConfigurationException("Config Node " + optionName + " is not a boolean");
}
private Option getOption(String optionName) throws ConfigurationException {
LinkedList<String> l = new LinkedList<String>();
for(String s : optionName.split("\\.")) {
l.addLast(s);
}
return getOption(root, l);
}
private Option getOption(Option parent, LinkedList<String> names) throws ConfigurationException {
if(names.size() == 0) {
return parent;
} else if(parent instanceof ParentOption) {
for(Option o2 : ((ParentOption) parent).getChildOptions()) {
if(o2.getIdentifier().equals(names.getFirst())) {
names.removeFirst();
return getOption(o2, names);
}
}
}
throw new ConfigurationException("Config Node doesn't exist");
}
public ParentOption getRoot() {
return root;
}
} }

View File

@ -1,27 +1,27 @@
package cc.co.evenprime.bukkit.nocheat.config; package cc.co.evenprime.bukkit.nocheat.config;
public abstract class Option { public abstract class Option {
private final String identifier; private final String identifier;
private Option parent; private Option parent;
public Option(String identifier) { public Option(String identifier) {
this.identifier = identifier; this.identifier = identifier;
} }
public final String getIdentifier() { public final String getIdentifier() {
return identifier; return identifier;
} }
public final void setParent(Option parent) { public final void setParent(Option parent) {
this.parent = parent; this.parent = parent;
} }
public final String getFullIdentifier() { public final String getFullIdentifier() {
return (parent == null || parent.getFullIdentifier() == "") ? identifier : parent.getFullIdentifier() + "." + identifier; return (parent == null || parent.getFullIdentifier() == "") ? identifier : parent.getFullIdentifier() + "." + identifier;
} }
public abstract String toYAMLString(String prefix); public abstract String toYAMLString(String prefix);
public abstract String toDescriptionString(String prefix); public abstract String toDescriptionString(String prefix);
} }

View File

@ -4,80 +4,75 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
public class ParentOption extends Option { public class ParentOption extends Option {
/** /**
* *
*/ */
private static final long serialVersionUID = 3162246550749560727L; private static final long serialVersionUID = 3162246550749560727L;
private final LinkedList<Option> children = new LinkedList<Option>(); private final LinkedList<Option> children = new LinkedList<Option>();
private final boolean editable; private final boolean editable;
public ParentOption(String identifier, boolean editable) { public ParentOption(String identifier, boolean editable) {
super(identifier); super(identifier);
this.editable = editable; this.editable = editable;
} }
public final Collection<Option> getChildOptions() { public final Collection<Option> getChildOptions() {
return Collections.unmodifiableCollection(children); return Collections.unmodifiableCollection(children);
} }
public final void add(Option option) { public final void add(Option option) {
children.addLast(option); children.addLast(option);
option.setParent(this); option.setParent(this);
} }
public final void remove(Option option) { public final void remove(Option option) {
if(editable) if(editable)
children.remove(option); children.remove(option);
} }
public boolean isEditable() { public boolean isEditable() {
return editable; return editable;
} }
@Override @Override
public String toYAMLString(String prefix) { public String toYAMLString(String prefix) {
String s = ""; String s = "";
if(getIdentifier().length() > 0) { if(getIdentifier().length() > 0) {
s += prefix + getIdentifier() + ":\r\n"; s += prefix + getIdentifier() + ":\r\n";
for(Option o : getChildOptions()) { for(Option o : getChildOptions()) {
s += o.toYAMLString(prefix + " "); s += o.toYAMLString(prefix + " ");
} }
} } else {
else for(Option o : getChildOptions()) {
{ s += o.toYAMLString(prefix);
for(Option o : getChildOptions()) { }
s += o.toYAMLString(prefix); }
}
}
return s; return s;
} }
@Override @Override
public String toDescriptionString(String prefix) { public String toDescriptionString(String prefix) {
String s = ""; String s = "";
if(getIdentifier().length() > 0) { if(getIdentifier().length() > 0) {
s += prefix + getIdentifier() + ":\r\n"; s += prefix + getIdentifier() + ":\r\n";
for(Option o : getChildOptions()) { for(Option o : getChildOptions()) {
s += o.toDescriptionString(prefix + " "); s += o.toDescriptionString(prefix + " ");
} }
} } else {
else for(Option o : getChildOptions()) {
{ s += o.toDescriptionString(prefix);
for(Option o : getChildOptions()) { }
s += o.toDescriptionString(prefix); }
}
}
return s; return s;
} }
} }

View File

@ -2,12 +2,12 @@ package cc.co.evenprime.bukkit.nocheat.config;
public class ShortStringOption extends TextFieldOption { public class ShortStringOption extends TextFieldOption {
/** /**
* *
*/ */
private static final long serialVersionUID = 2258827414736580449L; private static final long serialVersionUID = 2258827414736580449L;
public ShortStringOption(String name, String initialValue) { public ShortStringOption(String name, String initialValue) {
super(name, initialValue, 10); super(name, initialValue, 10);
} }
} }

View File

@ -2,44 +2,43 @@ package cc.co.evenprime.bukkit.nocheat.config;
public abstract class TextFieldOption extends ChildOption { public abstract class TextFieldOption extends ChildOption {
/** /**
* *
*/ */
private static final long serialVersionUID = -8189248456599421250L; private static final long serialVersionUID = -8189248456599421250L;
private String value; private String value;
private final int length; private final int length;
public TextFieldOption(String name, String initialValue, int preferredLength) { public TextFieldOption(String name, String initialValue, int preferredLength) {
super(name); super(name);
this.value = initialValue; this.value = initialValue;
this.length = preferredLength; this.length = preferredLength;
} }
@Override @Override
public String getValue() { public String getValue() {
return this.value; return this.value;
} }
public boolean setValue(String value) { public boolean setValue(String value) {
if(isValid(value)) { if(isValid(value)) {
this.value = value; this.value = value;
return true; return true;
} } else
else return false;
return false; }
}
protected boolean isValid(String value) { protected boolean isValid(String value) {
return value != null; return value != null;
} }
public int getPreferredLength() { public int getPreferredLength() {
return length; return length;
} }
public boolean hasPreferredLength() { public boolean hasPreferredLength() {
return length != -1; return length != -1;
} }
} }

View File

@ -1,9 +1,8 @@
package cc.co.evenprime.bukkit.nocheat.data; package cc.co.evenprime.bukkit.nocheat.data;
public class AirbuildData { public class AirbuildData {
public int perFiveSeconds = 0;
public int summaryTask = -1;
public int perFiveSeconds = 0;
public int summaryTask = -1;
} }

View File

@ -7,63 +7,60 @@ import net.minecraft.server.Block;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
public class MovingData { public class MovingData {
public int jumpPhase = 0;
public final int violationsInARow[] = { 0, 0, 0 };
public double horizFreedom = 0.0D;
public double vertFreedom = 0.0D;
public int vertFreedomCounter = 0;
// setbackpoint is a recommendation - try to teleport to first solid block below it public int jumpPhase = 0;
// for better effect public final int violationsInARow[] = {0, 0, 0};
public Location setBackPoint = null; public double horizFreedom = 0.0D;
public double vertFreedom = 0.0D;
public int vertFreedomCounter = 0;
public int summaryTask = -1; // setbackpoint is a recommendation - try to teleport to first solid block
public Level highestLogLevel = null; // below it
public double maxYVelocity = 0.0D; // for better effect
public double violationLevel = 0.0D; public Location setBackPoint = null;
public Location teleportInitializedByMe = null; public int summaryTask = -1;
public boolean wasTeleported = true; public Level highestLogLevel = null;
public Location teleportedTo; public double maxYVelocity = 0.0D;
public double violationLevel = 0.0D;
// Block types that may need to be treated specially public Location teleportInitializedByMe = null;
public static final int NONSOLID = 0; // 0x00000000
public static final int SOLID = 1; // 0x00000001
public static final int LIQUID = 2; // 0x00000010
public static final int LADDER = 4; // 0x00000100
public static final int FENCE = 8; // 0x00001000
// Block types that may need to be treated specially
public static final int NONSOLID = 0; // 0x00000000
public static final int SOLID = 1; // 0x00000001
public static final int LIQUID = 2; // 0x00000010
public static final int LADDER = 4; // 0x00000100
public static final int FENCE = 8; // 0x00001000
// Until I can think of a better way to determine if a block is solid or not, this is what I'll do // Until I can think of a better way to determine if a block is solid or
public static final int types[] = new int[256]; // not, this is what I'll do
public static final int types[] = new int[256];
static { static {
// Find and define properties of all blocks // Find and define properties of all blocks
for(int i = 0; i < types.length; i++) { for(int i = 0; i < types.length; i++) {
// Everything is considered solid at first // Everything is considered solid at first
types[i] = SOLID; types[i] = SOLID;
if(Block.byId[i] != null) { if(Block.byId[i] != null) {
if(Block.byId[i].material.isSolid()) { if(Block.byId[i].material.isSolid()) {
// solid blocks like STONE, CAKE, TRAPDOORS // solid blocks like STONE, CAKE, TRAPDOORS
types[i] = SOLID; types[i] = SOLID;
} } else if(Block.byId[i].material.isLiquid()) {
else if(Block.byId[i].material.isLiquid()){ // WATER, LAVA
// WATER, LAVA types[i] = LIQUID;
types[i] = LIQUID; } else {
} types[i] = NONSOLID;
else { }
types[i] = NONSOLID; }
} }
}
}
// Special types just for me // Special types just for me
types[Material.LADDER.getId()]= LADDER | SOLID; types[Material.LADDER.getId()] = LADDER | SOLID;
types[Material.FENCE.getId()]= FENCE | SOLID; types[Material.FENCE.getId()] = FENCE | SOLID;
} }
} }

View File

@ -1,23 +1,23 @@
package cc.co.evenprime.bukkit.nocheat.data; package cc.co.evenprime.bukkit.nocheat.data;
/** /**
* per player storage for data persistence between events * per player storage for data persistence between events
* *
* @author Evenprime * @author Evenprime
* *
*/ */
public class NoCheatData { public class NoCheatData {
/** /**
* Don't rely on any of these yet, they are likely going to change their name/functionality * Don't rely on any of these yet, they are likely going to change their
*/ * name/functionality
public MovingData moving; */
public SpeedhackData speedhack; public MovingData moving;
public AirbuildData airbuild; public SpeedhackData speedhack;
public AirbuildData airbuild;
public PermissionData permission; public PermissionData permission;
public NukeData nuke; public NukeData nuke;
public NoCheatData() { } public NoCheatData() {}
} }

View File

@ -1,8 +1,7 @@
package cc.co.evenprime.bukkit.nocheat.data; package cc.co.evenprime.bukkit.nocheat.data;
public class NukeData { public class NukeData {
public int counter = 0;
public int counter = 0;
} }

View File

@ -2,34 +2,34 @@ package cc.co.evenprime.bukkit.nocheat.data;
public class PermissionData { public class PermissionData {
public final long lastUpdate[] = new long[11]; public final long lastUpdate[] = new long[11];
public final boolean cache[] = new boolean[11]; public final boolean cache[] = new boolean[11];
public static final String[] permissionNames = new String[11]; public static final String[] permissionNames = new String[11];
public static final int PERMISSION_MOVING = 0; public static final int PERMISSION_MOVING = 0;
public static final int PERMISSION_FLYING = 1; public static final int PERMISSION_FLYING = 1;
public static final int PERMISSION_SPEEDHACK = 2; public static final int PERMISSION_SPEEDHACK = 2;
public static final int PERMISSION_AIRBUILD = 3; public static final int PERMISSION_AIRBUILD = 3;
public static final int PERMISSION_BEDTELEPORT = 4; // No longer used public static final int PERMISSION_BEDTELEPORT = 4; // unused
public static final int PERMISSION_BOGUSITEMS = 5; public static final int PERMISSION_BOGUSITEMS = 5;
public static final int PERMISSION_NOTIFY = 6; public static final int PERMISSION_NOTIFY = 6;
public static final int PERMISSION_ITEMDUPE = 7; // No longer used public static final int PERMISSION_ITEMDUPE = 7; // unused
public static final int PERMISSION_FAKESNEAK = 8; public static final int PERMISSION_FAKESNEAK = 8;
public static final int PERMISSION_FASTSWIM = 9; public static final int PERMISSION_FASTSWIM = 9;
public static final int PERMISSION_NUKE = 10; public static final int PERMISSION_NUKE = 10;
static { static {
permissionNames[PERMISSION_AIRBUILD] = "nocheat.airbuild"; permissionNames[PERMISSION_AIRBUILD] = "nocheat.airbuild";
permissionNames[PERMISSION_BEDTELEPORT] = "nocheat.bedteleport"; permissionNames[PERMISSION_BEDTELEPORT] = "nocheat.bedteleport";
permissionNames[PERMISSION_FLYING] = "nocheat.flying"; permissionNames[PERMISSION_FLYING] = "nocheat.flying";
permissionNames[PERMISSION_MOVING] = "nocheat.moving"; permissionNames[PERMISSION_MOVING] = "nocheat.moving";
permissionNames[PERMISSION_BOGUSITEMS] = "nocheat.bogusitems"; permissionNames[PERMISSION_BOGUSITEMS] = "nocheat.bogusitems";
permissionNames[PERMISSION_SPEEDHACK] = "nocheat.speedhack"; permissionNames[PERMISSION_SPEEDHACK] = "nocheat.speedhack";
permissionNames[PERMISSION_NOTIFY] = "nocheat.notify"; permissionNames[PERMISSION_NOTIFY] = "nocheat.notify";
permissionNames[PERMISSION_ITEMDUPE] = "nocheat.itemdupe"; permissionNames[PERMISSION_ITEMDUPE] = "nocheat.itemdupe";
permissionNames[PERMISSION_FAKESNEAK] = "nocheat.fakesneak"; permissionNames[PERMISSION_FAKESNEAK] = "nocheat.fakesneak";
permissionNames[PERMISSION_FASTSWIM] = "nocheat.fastswim"; permissionNames[PERMISSION_FASTSWIM] = "nocheat.fastswim";
permissionNames[PERMISSION_NUKE] = "nocheat.nuke"; permissionNames[PERMISSION_NUKE] = "nocheat.nuke";
} }
} }

View File

@ -4,10 +4,12 @@ import org.bukkit.Location;
public class SpeedhackData { public class SpeedhackData {
public int lastCheckTicks = 0; // timestamp of last check for speedhacks public int lastCheckTicks = 0; // timestamp of last
public Location setBackPoint = null; // check for speedhacks
public int eventsSinceLastCheck = 0; // used to identify speedhacks public Location setBackPoint = null;
public final int violationsInARow[] = { 0, 0, 0 }; public int eventsSinceLastCheck = 0; // used to identify
public int violationsInARowTotal = 0; // speedhacks
public final int violationsInARow[] = {0, 0, 0};
public int violationsInARowTotal = 0;
} }

View File

@ -9,19 +9,20 @@ import cc.co.evenprime.bukkit.nocheat.checks.AirbuildCheck;
* Handle events for all Block related events * Handle events for all Block related events
* *
* @author Evenprime * @author Evenprime
* *
*/ */
public class AirbuildBlockListener extends BlockListener { public class AirbuildBlockListener extends BlockListener {
private final AirbuildCheck check; private final AirbuildCheck check;
public AirbuildBlockListener(AirbuildCheck check) { public AirbuildBlockListener(AirbuildCheck check) {
this.check = check; this.check = check;
} }
@Override @Override
public void onBlockPlace(BlockPlaceEvent event) { public void onBlockPlace(BlockPlaceEvent event) {
if(!event.isCancelled()) check.check(event); if(!event.isCancelled())
} check.check(event);
}
} }

View File

@ -9,29 +9,30 @@ import cc.co.evenprime.bukkit.nocheat.checks.BogusitemsCheck;
public class BogusitemsPlayerListener extends PlayerListener { public class BogusitemsPlayerListener extends PlayerListener {
private final BogusitemsCheck check; private final BogusitemsCheck check;
public BogusitemsPlayerListener(BogusitemsCheck bogusitemsCheck) { public BogusitemsPlayerListener(BogusitemsCheck bogusitemsCheck) {
check = bogusitemsCheck; check = bogusitemsCheck;
} }
@Override @Override
public void onPlayerPickupItem(PlayerPickupItemEvent event) { public void onPlayerPickupItem(PlayerPickupItemEvent event) {
if(!event.isCancelled()) check.check(event); if(!event.isCancelled())
} check.check(event);
}
@Override @Override
public void onPlayerDropItem(PlayerDropItemEvent event) { public void onPlayerDropItem(PlayerDropItemEvent event) {
check.check(event); check.check(event);
} }
@Override @Override
public void onPlayerInteract(PlayerInteractEvent event) { public void onPlayerInteract(PlayerInteractEvent event) {
if(!event.isCancelled())
check.check(event);
}
if(!event.isCancelled()) check.check(event);
}
} }

View File

@ -1,6 +1,5 @@
package cc.co.evenprime.bukkit.nocheat.listeners; package cc.co.evenprime.bukkit.nocheat.listeners;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerListener; import org.bukkit.event.player.PlayerListener;
@ -18,39 +17,40 @@ import cc.co.evenprime.bukkit.nocheat.data.MovingData;
public class MovingPlayerListener extends PlayerListener { public class MovingPlayerListener extends PlayerListener {
private final MovingCheck check; private final MovingCheck check;
private final DataManager dataManager; private final DataManager dataManager;
public MovingPlayerListener(DataManager dataManager, MovingCheck check) { public MovingPlayerListener(DataManager dataManager, MovingCheck check) {
this.dataManager = dataManager; this.dataManager = dataManager;
this.check = check; this.check = check;
} }
@Override @Override
public void onPlayerMove(PlayerMoveEvent event) { public void onPlayerMove(PlayerMoveEvent event) {
if(event.isCancelled()) return; if(event.isCancelled())
return;
final Player player = event.getPlayer(); final Player player = event.getPlayer();
// Is there something to do at all? // Is there something to do at all?
if(!check.skipCheck(player)) { if(!check.skipCheck(player)) {
final MovingData data = dataManager.getMovingData(player); final MovingData data = dataManager.getMovingData(player);
final Location from = player.getLocation(); final Location from = player.getLocation();
final Location to = event.getTo(); final Location to = event.getTo();
Location newTo = null; Location newTo = null;
if(check.shouldBeApplied(player, data, from, to)) { if(!player.isInsideVehicle()) {
// Check it // Check it
newTo = check.check(player, from, to, data); newTo = check.check(player, from, to, data);
} }
// Did the checks decide we need a new To-Location? // Did the checks decide we need a new To-Location?
if(newTo != null) { if(newTo != null) {
event.setTo(new Location(newTo.getWorld(), newTo.getX(), newTo.getY(), newTo.getZ(), event.getTo().getYaw(), event.getTo().getPitch())); event.setTo(new Location(newTo.getWorld(), newTo.getX(), newTo.getY(), newTo.getZ(), event.getTo().getYaw(), event.getTo().getPitch()));
} }
} }
} }
} }

View File

@ -14,7 +14,7 @@ import cc.co.evenprime.bukkit.nocheat.data.MovingData;
/** /**
* *
* @author Evenprime * @author Evenprime
* *
*/ */
public class MovingPlayerMonitor extends PlayerListener { public class MovingPlayerMonitor extends PlayerListener {
@ -29,21 +29,20 @@ public class MovingPlayerMonitor extends PlayerListener {
@Override @Override
public void onPlayerRespawn(PlayerRespawnEvent event) { public void onPlayerRespawn(PlayerRespawnEvent event) {
MovingData data = dataManager.getMovingData(event.getPlayer()); MovingData data = dataManager.getMovingData(event.getPlayer());
data.wasTeleported = true;
data.setBackPoint = null; data.setBackPoint = null;
data.jumpPhase = 0; data.jumpPhase = 0;
} }
@Override @Override
public void onPlayerPortal(PlayerPortalEvent event) { public void onPlayerPortal(PlayerPortalEvent event) {
check.teleported(event); check.teleported(event);
} }
@Override @Override
public void onPlayerTeleport(PlayerTeleportEvent event) { public void onPlayerTeleport(PlayerTeleportEvent event) {
check.teleported(event); check.teleported(event);
} }
@Override @Override
public void onPlayerVelocity(PlayerVelocityEvent event) { public void onPlayerVelocity(PlayerVelocityEvent event) {
check.updateVelocity(event.getVelocity(), dataManager.getMovingData(event.getPlayer())); check.updateVelocity(event.getVelocity(), dataManager.getMovingData(event.getPlayer()));
@ -53,9 +52,9 @@ public class MovingPlayerMonitor extends PlayerListener {
public void onPlayerMove(PlayerMoveEvent event) { public void onPlayerMove(PlayerMoveEvent event) {
if(!event.isCancelled()) { if(!event.isCancelled()) {
if( event.getPlayer().isInsideVehicle()) { if(event.getPlayer().isInsideVehicle()) {
MovingData data = dataManager.getMovingData(event.getPlayer()); MovingData data = dataManager.getMovingData(event.getPlayer());
data.setBackPoint = event.getTo(); data.setBackPoint = null;
} }
} }
} }

View File

@ -7,17 +7,18 @@ import cc.co.evenprime.bukkit.nocheat.checks.NukeCheck;
public class NukeBlockListener extends BlockListener { public class NukeBlockListener extends BlockListener {
private final NukeCheck check; private final NukeCheck check;
public NukeBlockListener(NukeCheck check) { public NukeBlockListener(NukeCheck check) {
this.check = check; this.check = check;
} }
@Override @Override
public void onBlockBreak(BlockBreakEvent event) { public void onBlockBreak(BlockBreakEvent event) {
//System.out.println("Break "+ event.getPlayer() + " " + event.getBlock()); // System.out.println("Break "+ event.getPlayer() + " " +
check.check(event); // event.getBlock());
} check.check(event);
}
} }

View File

@ -9,25 +9,27 @@ import cc.co.evenprime.bukkit.nocheat.checks.SpeedhackCheck;
/** /**
* *
* @author Evenprime * @author Evenprime
* *
*/ */
public class SpeedhackPlayerListener extends PlayerListener { public class SpeedhackPlayerListener extends PlayerListener {
private final SpeedhackCheck check; private final SpeedhackCheck check;
public SpeedhackPlayerListener(SpeedhackCheck check) { public SpeedhackPlayerListener(SpeedhackCheck check) {
this.check = check; this.check = check;
} }
@Override @Override
public void onPlayerMove(PlayerMoveEvent event) { public void onPlayerMove(PlayerMoveEvent event) {
if(!event.isCancelled()) check.check(event); if(!event.isCancelled())
} check.check(event);
}
@Override @Override
public void onPlayerTeleport(PlayerTeleportEvent event) { public void onPlayerTeleport(PlayerTeleportEvent event) {
if(!event.isCancelled()) check.teleported(event); if(!event.isCancelled())
} check.teleported(event);
}
} }

View File

@ -16,52 +16,52 @@ import cc.co.evenprime.bukkit.nocheat.wizard.gui.ParentOptionGui;
public class Wizard extends JFrame { public class Wizard extends JFrame {
/** /**
* *
*/ */
private static final long serialVersionUID = 8798111079958779207L; private static final long serialVersionUID = 8798111079958779207L;
public Wizard() {
public Wizard() {
JScrollPane scrollable = new JScrollPane();
this.setDefaultCloseOperation(EXIT_ON_CLOSE); JScrollPane scrollable = new JScrollPane();
this.setContentPane(scrollable);
JPanel inside = new JPanel();
scrollable.setViewportView(inside);
inside.setLayout(new BoxLayout(inside,BoxLayout.Y_AXIS));
final NoCheatConfiguration config = new NoCheatConfiguration(new File("NoCheat/nocheat.yml"), new File("NoCheat/descriptions.txt"));
ParentOptionGui root2 = new ParentOptionGui(config.getRoot());
inside.add(root2);
JButton b = new JButton("Save");
b.addActionListener(new ActionListener() { this.setDefaultCloseOperation(EXIT_ON_CLOSE);
@Override this.setContentPane(scrollable);
public void actionPerformed(ActionEvent arg0) {
NoCheatConfiguration.writeConfigFile(new File("NoCheat/nocheat.yml"), config);
JOptionPane.showMessageDialog(null, "Saved");
} });
b.setAlignmentY(0.0F); JPanel inside = new JPanel();
inside.add(b); scrollable.setViewportView(inside);
this.doLayout(); inside.setLayout(new BoxLayout(inside, BoxLayout.Y_AXIS));
this.pack(); final NoCheatConfiguration config = new NoCheatConfiguration(new File("NoCheat/nocheat.yml"), new File("NoCheat/descriptions.txt"));
this.setSize(900, 700); ParentOptionGui root2 = new ParentOptionGui(config.getRoot());
this.setTitle("NoCheat configuration utility"); inside.add(root2);
}
JButton b = new JButton("Save");
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
NoCheatConfiguration.writeConfigFile(new File("NoCheat/nocheat.yml"), config);
JOptionPane.showMessageDialog(null, "Saved");
}
});
b.setAlignmentY(0.0F);
inside.add(b);
this.doLayout();
this.pack();
this.setSize(900, 700);
this.setTitle("NoCheat configuration utility");
}
} }

View File

@ -1,6 +1,5 @@
package cc.co.evenprime.bukkit.nocheat.wizard.gui; package cc.co.evenprime.bukkit.nocheat.wizard.gui;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
@ -21,145 +20,140 @@ import cc.co.evenprime.bukkit.nocheat.config.TextFieldOption;
public class ChildOptionGuiFactory { public class ChildOptionGuiFactory {
public static JComponent create(ChildOption option) { public static JComponent create(ChildOption option) {
if(option instanceof BooleanOption) { if(option instanceof BooleanOption) {
return createBoolean((BooleanOption)option); return createBoolean((BooleanOption) option);
} } else if(option instanceof TextFieldOption) {
else if(option instanceof TextFieldOption) { return createTextField((TextFieldOption) option);
return createTextField((TextFieldOption)option); } else if(option instanceof LevelOption) {
} return createLogLevel((LevelOption) option);
else if(option instanceof LevelOption) { } else if(option instanceof CustomActionOption) {
return createLogLevel((LevelOption)option); return createCustomAction((CustomActionOption) option);
} }
else if(option instanceof CustomActionOption) {
return createCustomAction((CustomActionOption)option);
}
throw new RuntimeException("Unknown ChildOption " + option); throw new RuntimeException("Unknown ChildOption " + option);
} }
private static JComboBox createLogLevel(final LevelOption option) { private static JComboBox createLogLevel(final LevelOption option) {
final JComboBox comboBox = new JComboBox(); final JComboBox comboBox = new JComboBox();
for(LevelOption.LogLevel o : LevelOption.LogLevel.values()) for(LevelOption.LogLevel o : LevelOption.LogLevel.values())
comboBox.addItem(o); comboBox.addItem(o);
comboBox.setSelectedItem(option.getOptionValue()); comboBox.setSelectedItem(option.getOptionValue());
comboBox.addActionListener(new ActionListener() { comboBox.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
option.setValue((LevelOption.LogLevel)comboBox.getSelectedItem()); option.setValue((LevelOption.LogLevel) comboBox.getSelectedItem());
} }
}); });
return comboBox; return comboBox;
} }
private static JPanel createCustomAction(final CustomActionOption option) { private static JPanel createCustomAction(final CustomActionOption option) {
final JPanel panel = new JPanel(); final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
final JTextField command = new JTextField(option.getCommandValue()); final JTextField command = new JTextField(option.getCommandValue());
command.setColumns(55); command.setColumns(55);
command.setInputVerifier(new InputVerifier() { command.setInputVerifier(new InputVerifier() {
@Override @Override
public boolean verify(JComponent arg0) { public boolean verify(JComponent arg0) {
option.setCommandValue(command.getText()); option.setCommandValue(command.getText());
return true; return true;
} }
}); });
final JCheckBox repeat = new JCheckBox(); final JCheckBox repeat = new JCheckBox();
repeat.setSelected(option.getRepeatValue()); repeat.setSelected(option.getRepeatValue());
repeat.addActionListener(new ActionListener() { repeat.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent arg0) { public void actionPerformed(ActionEvent arg0) {
option.setRepeatValue(repeat.isSelected()); option.setRepeatValue(repeat.isSelected());
} }
});
final JTextField firstAfter = new JTextField(String.valueOf(option.getFirstAfterValue())); });
firstAfter.setColumns(3); final JTextField firstAfter = new JTextField(String.valueOf(option.getFirstAfterValue()));
firstAfter.setInputVerifier(new InputVerifier() { firstAfter.setColumns(3);
@Override firstAfter.setInputVerifier(new InputVerifier() {
public boolean verify(JComponent arg0) {
int value;
try {
value = Integer.parseInt(firstAfter.getText());
option.setFirsttAfterValue(value);
return true;
}
catch(Exception e) {
JOptionPane.showMessageDialog(firstAfter, "Illegal value for this field");
firstAfter.setText(String.valueOf(option.getFirstAfterValue()));
return false;
}
}
});
panel.add(firstAfter); @Override
panel.add(repeat); public boolean verify(JComponent arg0) {
panel.add(command); int value;
try {
value = Integer.parseInt(firstAfter.getText());
option.setFirsttAfterValue(value);
return true;
} catch(Exception e) {
JOptionPane.showMessageDialog(firstAfter, "Illegal value for this field");
firstAfter.setText(String.valueOf(option.getFirstAfterValue()));
return false;
}
}
});
return panel; panel.add(firstAfter);
} panel.add(repeat);
panel.add(command);
private static JCheckBox createBoolean(final BooleanOption option) { return panel;
}
final JCheckBox checkBox = new JCheckBox(); private static JCheckBox createBoolean(final BooleanOption option) {
checkBox.setSelected(option.getBooleanValue());
checkBox.addActionListener(new ActionListener() {
@Override final JCheckBox checkBox = new JCheckBox();
public void actionPerformed(ActionEvent arg0) { checkBox.setSelected(option.getBooleanValue());
option.setValue(checkBox.isSelected()); checkBox.addActionListener(new ActionListener() {
} @Override
}); public void actionPerformed(ActionEvent arg0) {
option.setValue(checkBox.isSelected());
return checkBox; }
} });
private static JTextField createTextField(final TextFieldOption option) { return checkBox;
}
final JTextField textField = new JTextField(option.getValue()); private static JTextField createTextField(final TextFieldOption option) {
if(option.hasPreferredLength()) { final JTextField textField = new JTextField(option.getValue());
textField.setColumns(option.getPreferredLength());
}
textField.setInputVerifier(new InputVerifier() { if(option.hasPreferredLength()) {
textField.setColumns(option.getPreferredLength());
}
@Override textField.setInputVerifier(new InputVerifier() {
public boolean verify(JComponent arg0) {
if(option.setValue(textField.getText())){ @Override
return true; public boolean verify(JComponent arg0) {
}
else {
JOptionPane.showMessageDialog(textField, "Illegal value for this field");
textField.setText(option.getValue());
return false;
}
}
});
return textField; if(option.setValue(textField.getText())) {
} return true;
} else {
JOptionPane.showMessageDialog(textField, "Illegal value for this field");
textField.setText(option.getValue());
return false;
}
}
});
return textField;
}
} }

View File

@ -24,193 +24,183 @@ import cc.co.evenprime.bukkit.nocheat.config.ParentOption;
public class ParentOptionGui extends JPanel { public class ParentOptionGui extends JPanel {
/** /**
* *
*/ */
private static final long serialVersionUID = 5277750257203546802L; private static final long serialVersionUID = 5277750257203546802L;
private final ParentOption option; private final ParentOption option;
private final LinkedList<Option> children = new LinkedList<Option>(); private final LinkedList<Option> children = new LinkedList<Option>();
public ParentOptionGui(ParentOption option) { public ParentOptionGui(ParentOption option) {
this.option = option; this.option = option;
if(option.getIdentifier().length() > 0) { if(option.getIdentifier().length() > 0) {
this.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createCompoundBorder( this.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5), BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.BLACK), " " + option.getIdentifier() + ": "), BorderFactory.createEmptyBorder(5, 5, 5, 5))));
BorderFactory.createTitledBorder(BorderFactory.createMatteBorder(2, 2, }
2, 2, Color.BLACK), " " + option.getIdentifier() + ": "), this.setLayout(new GridBagLayout());
BorderFactory.createEmptyBorder(5,5,5,5))));
}
this.setLayout(new GridBagLayout());
recreateContent(); recreateContent();
} }
private void recreateContent() { private void recreateContent() {
this.removeAll(); this.removeAll();
this.children.clear(); this.children.clear();
int line = 0; int line = 0;
if(this.option.isEditable()) { if(this.option.isEditable()) {
final JTextField nameField = new JTextField("actionname");
nameField.setColumns(14);
JPanel p2 = new JPanel(); final JTextField nameField = new JTextField("actionname");
p2.add(nameField); nameField.setColumns(14);
JButton createNew = new JButton("new");
createNew.addActionListener(new ActionListener() {
@Override JPanel p2 = new JPanel();
public void actionPerformed(ActionEvent arg0) { p2.add(nameField);
option.add(new CustomActionOption(nameField.getText(), "yourcommand [player]"));
recreateContent();
}
});
JPanel p = new JPanel();
p.add(createNew);
GridBagConstraints c = new GridBagConstraints();
JButton createNew = new JButton("new");
createNew.addActionListener(new ActionListener() {
c.gridx = 0;
c.gridy = line;
c.gridwidth = 1;
c.anchor = GridBagConstraints.WEST;
c.ipadx = 5;
c.ipady = 15;
c.weightx = 1;
this.add(p, c);
c.gridx = 1;
c.gridy = line;
c.gridwidth = 3;
c.anchor = GridBagConstraints.WEST;
c.ipadx = 5;
c.ipady = 15;
c.weightx = 1;
@Override
public void actionPerformed(ActionEvent arg0) {
this.add(p2, c); option.add(new CustomActionOption(nameField.getText(), "yourcommand [player]"));
line++; recreateContent();
} }
});
for(Option o : this.option.getChildOptions()) { JPanel p = new JPanel();
add(o, line); p.add(createNew);
children.add(o);
line++;
}
this.revalidate(); GridBagConstraints c = new GridBagConstraints();
}
private void add(final Option child, int line) { c.gridx = 0;
if(child instanceof ParentOption) { c.gridy = line;
GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1;
c.anchor = GridBagConstraints.WEST;
c.ipadx = 5;
c.ipady = 15;
c.weightx = 1;
c.gridx = 0; this.add(p, c);
c.gridy = line;
c.gridwidth = 4; // Spans over three columns c.gridx = 1;
if(this.option.isEditable()) c.gridwidth = 5; // Spans over four columns c.gridy = line;
c.anchor = GridBagConstraints.WEST; c.gridwidth = 3;
c.ipadx = 5; c.anchor = GridBagConstraints.WEST;
c.ipady = 15; c.ipadx = 5;
c.weightx = 1; c.ipady = 15;
c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1;
this.add(new ParentOptionGui((ParentOption)child), c); this.add(p2, c);
} line++;
else if(child instanceof ChildOption) }
{
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0; for(Option o : this.option.getChildOptions()) {
c.gridy = line; add(o, line);
c.gridwidth = 1; children.add(o);
c.anchor = GridBagConstraints.WEST; line++;
c.ipadx = 10; }
c.weightx = 0;
this.add(new JLabel(child.getIdentifier() + ":"), c); this.revalidate();
}
c.gridx++; private void add(final Option child, int line) {
c.gridy = line; if(child instanceof ParentOption) {
c.gridwidth = 1; GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.WEST;
c.ipadx = 5;
c.weightx = 0;
c.fill = GridBagConstraints.HORIZONTAL;
JComponent tmp = ChildOptionGuiFactory.create((ChildOption)child); c.gridx = 0;
c.gridy = line;
this.add(tmp, c); c.gridwidth = 4; // Spans over three columns
if(this.option.isEditable())
c.gridx++; c.gridwidth = 5; // Spans over four columns
c.gridy = line; c.anchor = GridBagConstraints.WEST;
c.gridwidth = 1; c.ipadx = 5;
c.anchor = GridBagConstraints.CENTER; c.ipady = 15;
c.ipadx = 0; c.weightx = 1;
c.insets = new Insets(0, 15, 0, 5); c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0;
JButton help = new JButton("?");
help.addActionListener(new ActionListener() {
@Override this.add(new ParentOptionGui((ParentOption) child), c);
public void actionPerformed(ActionEvent arg0) { } else if(child instanceof ChildOption) {
GridBagConstraints c = new GridBagConstraints();
JOptionPane.showMessageDialog(null, Explainations.get(((ChildOption)child).getFullIdentifier()), "Description of "+ ((ChildOption)child).getFullIdentifier(), JOptionPane.INFORMATION_MESSAGE);
}
});
help.setMargin(new Insets(0, 0, 0, 0));
this.add(help, c);
c.gridx++; c.gridx = 0;
c.gridy = line; c.gridy = line;
c.gridwidth = 1; c.gridwidth = 1;
c.anchor = GridBagConstraints.WEST; c.anchor = GridBagConstraints.WEST;
c.ipadx = 5; c.ipadx = 10;
c.weightx = 1; c.weightx = 0;
this.add(Box.createHorizontalGlue(), c); this.add(new JLabel(child.getIdentifier() + ":"), c);
if(this.option.isEditable()) {
c.gridx++;
c.gridy = line;
c.gridwidth = 1;
c.anchor = GridBagConstraints.WEST;
c.ipadx = 5;
c.weightx = 1;
JButton removeButton = new JButton("delete"); c.gridx++;
c.gridy = line;
c.gridwidth = 1;
c.anchor = GridBagConstraints.WEST;
c.ipadx = 5;
c.weightx = 0;
c.fill = GridBagConstraints.HORIZONTAL;
removeButton.addActionListener(new ActionListener() { JComponent tmp = ChildOptionGuiFactory.create((ChildOption) child);
@Override this.add(tmp, c);
public void actionPerformed(ActionEvent arg0) {
option.remove(child);
recreateContent();
}
});
this.add(removeButton, c); c.gridx++;
} c.gridy = line;
} c.gridwidth = 1;
c.anchor = GridBagConstraints.CENTER;
c.ipadx = 0;
c.insets = new Insets(0, 15, 0, 5);
c.weightx = 0;
} JButton help = new JButton("?");
help.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(null, Explainations.get(((ChildOption) child).getFullIdentifier()), "Description of " + ((ChildOption) child).getFullIdentifier(), JOptionPane.INFORMATION_MESSAGE);
}
});
help.setMargin(new Insets(0, 0, 0, 0));
this.add(help, c);
c.gridx++;
c.gridy = line;
c.gridwidth = 1;
c.anchor = GridBagConstraints.WEST;
c.ipadx = 5;
c.weightx = 1;
this.add(Box.createHorizontalGlue(), c);
if(this.option.isEditable()) {
c.gridx++;
c.gridy = line;
c.gridwidth = 1;
c.anchor = GridBagConstraints.WEST;
c.ipadx = 5;
c.weightx = 1;
JButton removeButton = new JButton("delete");
removeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
option.remove(child);
recreateContent();
}
});
this.add(removeButton, c);
}
}
}
} }

View File

@ -15,135 +15,127 @@ import java.util.Set;
* An extremely simple YAML parser, not feature complete, but good enough for me * An extremely simple YAML parser, not feature complete, but good enough for me
* *
* @author Evenprime * @author Evenprime
* *
*/ */
public class SimpleYaml { public class SimpleYaml {
private static final String prefix = " "; private static final String prefix = " ";
private SimpleYaml() {}
public static Map<String, Object> read(File file) throws IOException {
Map<String, Object> root = new HashMap<String, Object>();
BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
LinkedList<String> lines = new LinkedList<String>();
String line = null;
while(( line = r.readLine()) != null) {
lines.add(line);
}
r.close();
return parse(root, lines, "");
}
private static Map<String, Object> parse(Map<String, Object> root, LinkedList<String> lines, String prefix) throws IOException { private SimpleYaml() {}
String line = null; public static Map<String, Object> read(File file) throws IOException {
while(!lines.isEmpty()) {
line = lines.getFirst();
if(line.trim().startsWith("#")) { lines.removeFirst(); }
else if(line.trim().isEmpty()) { lines.removeFirst(); }
else if(line.startsWith(prefix)) {
lines.removeFirst();
if(line.contains(":")) {
String pair[] = line.split(":", 2);
if(pair[1].trim().isEmpty()) {
Map<String, Object> m = new HashMap<String, Object>();
root.put(pair[0].trim(), parse(m, lines, prefix + SimpleYaml.prefix));
}
else
{
root.put(pair[0].trim(), removeQuotationMarks(pair[1].trim()));
}
}
}
else break;
}
return root;
}
private static String removeQuotationMarks(String s) {
if(s.startsWith("\"") && s.endsWith("\"")) {
return s.substring(1, s.length() -1);
}
else if(s.startsWith("\'") && s.endsWith("\'")) {
return s.substring(1, s.length() -1);
}
return s;
} Map<String, Object> root = new HashMap<String, Object>();
/* Convenience methods for retrieving values start here */
@SuppressWarnings("unchecked")
private final static Object getProperty(String path, Map<String, Object> node) {
if (!path.contains(".")) {
return node.get(path);
}
else
{
String[] parts = path.split("\\.", 2);
return getProperty(parts[1], (Map<String, Object>) node.get(parts[0]));
}
}
@SuppressWarnings("unchecked")
public static Set<String> getKeys(String path, Map<String, Object> node) {
try {
return ((Map<String, Object>)getProperty(path, node)).keySet();
}
catch(Exception e) {
//e.printStackTrace();
return new HashSet<String>();
}
}
public static int getInt(String path, int defaultValue, Map<String, Object> node) { BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
try {
return Integer.parseInt((String)getProperty(path, node));
}
catch(Exception e) {
//e.printStackTrace();
return defaultValue;
}
}
public static boolean getBoolean(String path, boolean defaultValue, Map<String, Object> node) { LinkedList<String> lines = new LinkedList<String>();
try {
if(((String)getProperty(path, node)).equals("true")) {
return true;
} else if(((String)getProperty(path, node)).equals("false")) {
return false;
}
else {
return defaultValue;
}
}
catch(Exception e) {
//e.printStackTrace();
return defaultValue;
}
}
public static String getString(String path, String defaultValue, Map<String, Object> node) { String line = null;
try {
String result = (String) getProperty(path, node); while((line = r.readLine()) != null) {
if(result == null) return defaultValue; lines.add(line);
return result; }
}
catch(Exception e) { r.close();
return defaultValue;
} return parse(root, lines, "");
}
}
private static Map<String, Object> parse(Map<String, Object> root, LinkedList<String> lines, String prefix) throws IOException {
String line = null;
while(!lines.isEmpty()) {
line = lines.getFirst();
if(line.trim().startsWith("#")) {
lines.removeFirst();
} else if(line.trim().isEmpty()) {
lines.removeFirst();
} else if(line.startsWith(prefix)) {
lines.removeFirst();
if(line.contains(":")) {
String pair[] = line.split(":", 2);
if(pair[1].trim().isEmpty()) {
Map<String, Object> m = new HashMap<String, Object>();
root.put(pair[0].trim(), parse(m, lines, prefix + SimpleYaml.prefix));
} else {
root.put(pair[0].trim(), removeQuotationMarks(pair[1].trim()));
}
}
} else
break;
}
return root;
}
private static String removeQuotationMarks(String s) {
if(s.startsWith("\"") && s.endsWith("\"")) {
return s.substring(1, s.length() - 1);
} else if(s.startsWith("\'") && s.endsWith("\'")) {
return s.substring(1, s.length() - 1);
}
return s;
}
/* Convenience methods for retrieving values start here */
@SuppressWarnings("unchecked")
private final static Object getProperty(String path, Map<String, Object> node) {
if(!path.contains(".")) {
return node.get(path);
} else {
String[] parts = path.split("\\.", 2);
return getProperty(parts[1], (Map<String, Object>) node.get(parts[0]));
}
}
@SuppressWarnings("unchecked")
public static Set<String> getKeys(String path, Map<String, Object> node) {
try {
return ((Map<String, Object>) getProperty(path, node)).keySet();
} catch(Exception e) {
// e.printStackTrace();
return new HashSet<String>();
}
}
public static int getInt(String path, int defaultValue, Map<String, Object> node) {
try {
return Integer.parseInt((String) getProperty(path, node));
} catch(Exception e) {
// e.printStackTrace();
return defaultValue;
}
}
public static boolean getBoolean(String path, boolean defaultValue, Map<String, Object> node) {
try {
if(((String) getProperty(path, node)).equals("true")) {
return true;
} else if(((String) getProperty(path, node)).equals("false")) {
return false;
} else {
return defaultValue;
}
} catch(Exception e) {
// e.printStackTrace();
return defaultValue;
}
}
public static String getString(String path, String defaultValue, Map<String, Object> node) {
try {
String result = (String) getProperty(path, node);
if(result == null)
return defaultValue;
return result;
} catch(Exception e) {
return defaultValue;
}
}
} }