(BIG CHANGE) Internal structure and hooks.

This commit is contained in:
asofold 2012-08-07 19:38:17 +02:00
parent 7d3ba1e3eb
commit 447ef2f4a9
6 changed files with 112 additions and 187 deletions

View File

@ -23,6 +23,7 @@ VERSION HISTORY
---------------------------
(4.0.0)
- (BIG CHANGE) Internal structure and hooks.
(3.0.0)
- (BIG CHANGE) Back to NoCheatPlus !

View File

@ -1,10 +1,10 @@
package me.asofold.bpl.cncp;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
@ -12,7 +12,8 @@ import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import me.asofold.bpl.cncp.config.compatlayer.NewConfig;
import me.asofold.bpl.cncp.hooks.Hook;
import me.asofold.bpl.cncp.hooks.generic.HookPlayerClass;
import me.asofold.bpl.cncp.setttings.GroupHooks;
import me.asofold.bpl.cncp.hooks.ncp.NCPHook;
import me.asofold.bpl.cncp.hooks.ncp.NCPHookManager;
import me.asofold.bpl.cncp.setttings.Settings;
import me.asofold.bpl.cncp.utils.Utils;
@ -43,15 +44,6 @@ import fr.neatmonster.nocheatplus.checks.moving.SurvivalFly.SurvivalFlyEvent;
*/
public class CompatNoCheatPlus extends JavaPlugin implements Listener {
/**
* Storage of hooks that are called for all events.
*/
private static final ArrayList<Hook> hooksAll = new ArrayList<Hook>(10);
/**
* Storage of hooks that are called for certain groups and checks.
*/
private static final Map<String, GroupHooks> hooksGroups = new HashMap<String, GroupHooks>(20);
private final Settings settings = new Settings();
@ -100,16 +92,29 @@ public class CompatNoCheatPlus extends JavaPlugin implements Listener {
}
/**
* API to add a hook.
* API to add a hook. Adds the hook AND registers listeners if enabled. Also respects the configuration for preventing hooks.<br>
* If you want to not register the listeners use NCPHookManager.
* @param hook
* @return
*/
public static boolean addHook(Hook hook){
if (!enabled) return false;
if (Settings.preventAddHooks.contains(hook.getHookName())){
System.out.println("[cncp] Prevented adding hook: "+hook.getHookName() + " / " + hook.getHookVersion());
return false;
}
if (enabled) registerListeners(hook);
Integer[] checkIds = hook.getCheckSpec();
NCPHookManager.addHook(checkIds, hook); // This logs the message.
return true;
}
/**
* Conveniently register the listeners, do not use if you add/added the hook with addHook.
* @param hook
* @return
*/
public static boolean registerListeners(Hook hook) {
if (!enabled) return false;
Listener[] listeners = hook.getListeners();
if (listeners != null){
// attempt to register events:
@ -120,40 +125,9 @@ public class CompatNoCheatPlus extends JavaPlugin implements Listener {
pm.registerEvents(listener, plg);
}
}
String[][] specs = hook.getCheckSpec();
if (specs == null) hooksAll.add(hook);
else{
for (String[] spec : specs){
String group = spec[0].trim().toLowerCase();
GroupHooks gh = hooksGroups.get(group);
if (gh == null){
gh = new GroupHooks();
hooksGroups.put(group, gh);
}
if (spec.length == 1) gh.all.add(hook);
else{
for (int i = 1; i < spec.length; i++){
String check = spec[i].trim().toLowerCase();
ArrayList<Hook> hooks = gh.byCheck.get(check);
if (hooks == null){
hooks = new ArrayList<Hook>(10);
gh.byCheck.put(check, hooks);
}
hooks.add(hook);
}
}
}
}
System.out.println("[cncp] Added hook: "+hook.getHookName() + " / " + hook.getHookVersion());
return true;
}
public void clearHooks() {
hooksAll.clear();
hooksGroups.clear();
}
/**
* Add standard hooks if available.
*/
@ -167,8 +141,9 @@ public class CompatNoCheatPlus extends JavaPlugin implements Listener {
@Override
public void onEnable() {
// cleanup
clearHooks();
enabled = false; // make sure
// (no cleanup)
// Settings:
settings.clear();
reloadSettings();
@ -176,9 +151,27 @@ public class CompatNoCheatPlus extends JavaPlugin implements Listener {
final PluginManager pm = getServer().getPluginManager();
pm.registerEvents(this, this);
super.onEnable();
enabled = true;
// Add Hooks:
addAvailableHooks();
addAvailableHooks(); // add before enable is set to not yet register listeners.
enabled = true;
// register all listeners:
for (Hook hook : getAllHooks()){
registerListeners(hook);
}
}
/**
* Get all cncp Hook instances that are registered with NCPHookManager.
* @return
*/
public static Collection<Hook> getAllHooks() {
List<Hook> hooks = new LinkedList<Hook>();
for (NCPHook hook : NCPHookManager.getAllHooks()){
if (hook instanceof Hook) hooks.add((Hook) hook);
}
return hooks;
}
public boolean reloadSettings() {
@ -244,80 +237,32 @@ public class CompatNoCheatPlus extends JavaPlugin implements Listener {
@Override
public void onDisable() {
enabled = false;
clearHooks();
// remove all registered cncp hooks:
for (Hook hook : getAllHooks()){
NCPHookManager.removeHook(hook);
}
super.onDisable();
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled=true)
final void onCheckFail(final CheckEvent event){
// Check hooks, most specific first:
final String gn;
final String cn;
// TODO: This will be replaced by NCP invoking NCPHookManager.should... directly.
if (event instanceof SurvivalFlyEvent){
gn = "moving";
cn = "survivalfly";
}
else if (event instanceof CreativeFlyEvent){
gn = "moving";
cn = "creativefly";
}
else if (event instanceof NoFallEvent){
gn = "moving";
cn = "nofall";
}
else if (event instanceof FastBreakEvent){
gn = "blockbreak";
cn = "fastbreak";
}
else if (event instanceof NoSwingEvent){
gn = "blockbreak";
cn = "noswing";
}
else if (event instanceof DirectionEvent){
gn = "blockbreak";
cn = "direction";
}
else if (event instanceof SpeedEvent){
gn = "fight";
cn = "speed";
}
else if (event instanceof AngleEvent){
gn = "fight";
cn = "angle";
}
else{
// TODO: ...
gn = "";
cn = "";
}
final Integer checkId;
final GroupHooks gh = hooksGroups.get(gn.trim().toLowerCase());
if (gh != null){
final ArrayList<Hook> hooks = gh.byCheck.get(cn.trim().toLowerCase());
if (hooks != null) applyHooks(gn, cn, event, hooks);
if (event.isCancelled()) return;
if (!gh.all.isEmpty()) applyHooks(gn, cn, event, gh.all);
}
if (event.isCancelled()) return;
if (!hooksAll.isEmpty()) applyHooks(gn, cn, event, hooksAll);
}
private final void applyHooks(final String group, final String check, final CheckEvent event, final ArrayList<Hook> hooks) {
for (int i = 0; i < hooks.size(); i++){
if (event.isCancelled()) return;
final Hook hook = hooks.get(i);
try{
hook.processEvent(group, check, event);
}
catch (final Throwable t){
final Logger logger = getServer().getLogger();
logger.warning("[cncp][" + group + "/" + check + "] Unexpected exception on for hook ("+hook.getHookName()+" / "+hook.getHookVersion()+"):");
// TODO: maybe add more info about the CheckEvent ?
logger.warning(Utils.toString(t));
}
}
// horrible :)
if (event instanceof SurvivalFlyEvent) checkId = NCPHookManager.MOVING_SURVIVALFLY;
else if (event instanceof CreativeFlyEvent) checkId = NCPHookManager.MOVING_CREATIVEFLY;
else if (event instanceof NoFallEvent) checkId = NCPHookManager.MOVING_NOFALL;
else if (event instanceof FastBreakEvent) checkId = NCPHookManager.BLOCKBREAK_FASTBREAK;
else if (event instanceof NoSwingEvent) checkId = NCPHookManager.BLOCKBREAK_NOSWING;
else if (event instanceof DirectionEvent) checkId = NCPHookManager.BLOCKBREAK_DIRECTION;
else if (event instanceof SpeedEvent) checkId = NCPHookManager.FIGHT_SPEED;
else if (event instanceof AngleEvent) checkId = NCPHookManager.FIGHT_ANGLE;
else checkId = NCPHookManager.UNKNOWN;
if (NCPHookManager.shouldCancelVLProcessing(checkId, event.getPlayer())) event.setCancelled(true);
}
}

View File

@ -13,7 +13,7 @@ import org.bukkit.event.Listener;
public abstract class AbstractHook implements Hook{
@Override
public String[][] getCheckSpec() {
public Integer[] getCheckSpec() {
// Handle all CheckEvents (improbable).
return null;
}

View File

@ -1,39 +1,24 @@
package me.asofold.bpl.cncp.hooks;
import me.asofold.bpl.cncp.hooks.ncp.NCPHook;
import org.bukkit.event.Listener;
import fr.neatmonster.nocheatplus.checks.CheckEvent;
/**
* Interface for hooking into another plugin.<br>
* NOTE: You also have to implement the methods described in NCPHook.<br>
* If you do not use listeners or don't want the prevent-hooks configuration feature
* to take effect, you can also register directly with NCPHookManager.
*
* @author mc_dev
*
*/
public interface Hook{
/**
* Must not cause exceptions.
* @return
*/
public String getHookName();
public interface Hook extends NCPHook{
/**
* Must not cause exceptions.
* @return
* The check ids to register for, see NCPHookManager for reference, you can use ALL,
*/
public String getHookVersion();
/**
* Get the specification for which checks to call this.<br>
* <hr>
* The return value should be an array of arrays, each of which specifies the group name and the check names within that group.<br>
* You can return null to register for ALL checks.<br>
* You can just register the group name to get all checks for that group.<br>
* <hr>
* Currently group and check names are processed with trim().toLowerCase() !
* @return (see description)
*/
public String[][] getCheckSpec();
public Integer[] getCheckSpec();
/**
* Get listener instances to be registered with cncp.
@ -41,13 +26,4 @@ public interface Hook{
*/
public Listener[] getListeners();
/**
* This will only be called if the event has not yet been cancelled !<br>
* Cancel the event, and no further hooks will process this.
* @param group Name of check group
* @param check Name of check .
* @param event
*/
public void processEvent(final String group, final String check, final CheckEvent event);
}

View File

@ -5,7 +5,8 @@ import java.util.HashSet;
import java.util.Set;
import me.asofold.bpl.cncp.hooks.AbstractHook;
import fr.neatmonster.nocheatplus.checks.CheckEvent;
import org.bukkit.entity.Player;
public final class HookPlayerClass extends AbstractHook {
@ -51,27 +52,30 @@ public final class HookPlayerClass extends AbstractHook {
return "0.1";
}
@Override
public final void processEvent(final String group, final String check, final CheckEvent event) {
if (exemptAll && !event.getPlayer().getClass().getSimpleName().equals(playerClassName)) event.setCancelled(true);
public final boolean onCheckFailure(final Integer groupId, final Integer checkId, final Player player) {
if (exemptAll && !player.getClass().getSimpleName().equals(playerClassName)) return true;
else {
if (classNames.isEmpty()) return;
final Class<?> clazz = event.getPlayer().getClass();
if (classNames.isEmpty()) return false;
final Class<?> clazz = player.getClass();
final String name = clazz.getSimpleName();
if (classNames.contains(name)) event.setCancelled(true);
if (classNames.contains(name)) return true;
else if (checkSuperClass){
while (true){
final Class<?> superClass = clazz.getSuperclass();
if (superClass == null) return;
final String superName = superClass.getSimpleName();
if (superName.equals("Object")) return;
else if (classNames.contains(superName)){
event.setCancelled(true);
return;
if (superClass == null) return false;
else{
final String superName = superClass.getSimpleName();
if (superName.equals("Object")) return false;
else if (classNames.contains(superName)){
return true;
}
}
}
}
}
return false; // ECLIPSE
}
}

View File

@ -4,6 +4,7 @@ import java.util.HashMap;
import java.util.Map;
import me.asofold.bpl.cncp.hooks.AbstractHook;
import me.asofold.bpl.cncp.hooks.ncp.NCPHookManager;
import me.asofold.bpl.cncp.utils.PluginGetter;
import org.bukkit.entity.Entity;
@ -17,20 +18,18 @@ import com.gmail.nossr50.events.fake.FakeBlockBreakEvent;
import com.gmail.nossr50.events.fake.FakeBlockDamageEvent;
import com.gmail.nossr50.events.fake.FakeEntityDamageByEntityEvent;
import fr.neatmonster.nocheatplus.checks.CheckEvent;
public final class HookmcMMO extends AbstractHook implements Listener {
private static final Map<String, Integer> cancelChecksBlockBreak = new HashMap<String, Integer>();
private static final Map<String, Integer> cancelChecksBlockDamage = new HashMap<String, Integer>();
private static final Map<String, Integer> cancelChecksDamage = new HashMap<String, Integer>();
private static final Map<Integer, Integer> cancelChecksBlockBreak = new HashMap<Integer, Integer>();
private static final Map<Integer, Integer> cancelChecksBlockDamage = new HashMap<Integer, Integer>();
private static final Map<Integer, Integer> cancelChecksDamage = new HashMap<Integer, Integer>();
static{
cancelChecksBlockBreak.put("noswing", 1);
cancelChecksBlockBreak.put("fastbreak", 2);
cancelChecksBlockDamage.put("fastbreak", 1);
cancelChecksBlockBreak.put(NCPHookManager.BLOCKBREAK_NOSWING, 1);
cancelChecksBlockBreak.put(NCPHookManager.BLOCKBREAK_FASTBREAK, 2);
cancelChecksBlockDamage.put(NCPHookManager.BLOCKBREAK_FASTBREAK, 1);
cancelChecksDamage.put("angle", 1);
cancelChecksDamage.put("speed", 1);
cancelChecksDamage.put(NCPHookManager.FIGHT_ANGLE, 1);
cancelChecksDamage.put(NCPHookManager.FIGHT_SPEED, 1);
}
public HookmcMMO(){
@ -43,7 +42,7 @@ public final class HookmcMMO extends AbstractHook implements Listener {
private String cancel = null;
private long cancelTicks = 0;
private final Map<String, Integer> cancelChecks = new HashMap<String, Integer>();
private final Map<Integer, Integer> cancelChecks = new HashMap<Integer, Integer>();
@ -58,10 +57,10 @@ public final class HookmcMMO extends AbstractHook implements Listener {
}
@Override
public String[][] getCheckSpec() {
return new String[][]{
{"blockbreak", "fastbreak", "noswing"},
{"fight", "angle", "speed"},
public Integer[] getCheckSpec() {
return new Integer[]{
NCPHookManager.BLOCKBREAK_FASTBREAK, NCPHookManager.BLOCKBREAK_NOSWING,
NCPHookManager.FIGHT_ANGLE, NCPHookManager.FIGHT_SPEED,
};
}
@ -71,14 +70,14 @@ public final class HookmcMMO extends AbstractHook implements Listener {
return new Listener[]{this, fetch};
}
private final void setPlayer(final Entity entity, Map<String, Integer> cancelChecks){
private final void setPlayer(final Entity entity, Map<Integer, Integer> cancelChecks){
if (entity instanceof Player){
setPlayer((Player) entity, cancelChecks);
}
// no projectiles etc.
}
private final void setPlayer(final Player player, Map<String, Integer> cancelChecks){
private final void setPlayer(final Player player, Map<Integer, Integer> cancelChecks){
cancel = player.getName();
cancelTicks = player.getTicksLived();
this.cancelChecks.clear();
@ -119,15 +118,14 @@ public final class HookmcMMO extends AbstractHook implements Listener {
// cancel = null;
// }
@Override
public void processEvent(final String group, final String check, final CheckEvent event) {
public final boolean onCheckFailure(final Integer groupId, final Integer checkId, final Player player) {
// System.out.println("[cncp] Handle event: " + event.getEventName());
if (cancel == null){
// System.out.println("[cncp] Return on cancel == null: "+event.getPlayer().getName());
return;
return false;
}
final Player player = event.getPlayer();
final String name = player.getName();
if (cancel.equals(name)){
@ -137,21 +135,22 @@ public final class HookmcMMO extends AbstractHook implements Listener {
cancel = null;
}
else{
final Integer n = cancelChecks.get(check);
final Integer n = cancelChecks.get(checkId);
if (n == null){
// System.out.println("[cncp] Expired("+check+"): "+event.getPlayer().getName());
return;
return false;
}
else if (n > 0){
// System.out.println("Check with n = "+n);
if (n == 1) cancelChecks.remove(check);
else cancelChecks.put(check, n - 1);
if (n == 1) cancelChecks.remove(checkId);
else cancelChecks.put(checkId, n - 1);
}
// else: allow arbitrary numbers
// System.out.println("[cncp] Cancel: "+event.getPlayer().getName());
event.setCancelled(true);
return true;
}
}
return false;
}
}