This commit is contained in:
FancyBelt798245 2023-05-21 12:23:09 -04:00 committed by GitHub
commit 85e13cab62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 5208 additions and 4527 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
/target/
.classpath
.DS_Store
.project
.settings/org.eclipse.core.resources.prefs
*.prefs

View File

@ -1,8 +0,0 @@
/.settings
/.classpath
/.project
/jar_desc.jardesc
/target
/bin
/.gitignore
/local-maven/

View File

@ -1,121 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>CompatNoCheatPlus</groupId>
<artifactId>CompatNoCheatPlus</artifactId>
<version>6.6.6-SNAPSHOT</version>
<name>CompatNoCheatPlus</name>
<!-- Source code -->
<scm>
<developerConnection>scm:git:git@github.com:asofold/${project.name}.git</developerConnection>
<connection>scm:git:git://github.com/asofold/${project.name}.git</connection>
<url>https://github.com/asofold/${project.name}</url>
</scm>
<!-- Repositories -->
<repositories>
<repository>
<id>spigot-repo</id>
<url>http://hub.spigotmc.org/nexus/content/repositories/snapshots</url>
</repository>
<repository>
<id>md_5-snapshots</id>
<url>http://repo.md-5.net/content/repositories/snapshots/</url>
</repository>
<repository>
<id>md_5-releases</id>
<url>http://repo.md-5.net/content/repositories/releases/</url>
</repository>
<repository>
<id>cititensnpcs</id>
<url>http://repo.citizensnpcs.co/</url>
</repository>
<repository>
<id>drtshock-repo</id>
<url>http://ci.drtshock.net/plugin/repository/everything/</url>
</repository>
</repositories>
<!-- Dependencies -->
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.8.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.gmail.nossr50.mcMMO</groupId>
<artifactId>mcMMO</artifactId>
<version>1.5.04-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>fr.neatmonster</groupId>
<artifactId>nocheatplus</artifactId>
<version>3.16.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.citizensnpcs</groupId>
<artifactId>citizensapi</artifactId>
<version>2.0.16-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- Building -->
<build>
<defaultGoal>clean package</defaultGoal>
<sourceDirectory>${basedir}/src</sourceDirectory>
<resources>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>${basedir}</directory>
<includes>
<include>plugin.yml</include>
<include>LICENSE.txt</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<finalName>cncp</finalName>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
<pomPropertiesFile>false</pomPropertiesFile>
<manifest>
<addDefaultSpecificationEntries>false</addDefaultSpecificationEntries>
<addDefaultImplementationEntries>false</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<!-- Properties -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<BUILD_SERIES>?</BUILD_SERIES>
<BUILD_NUMBER>?</BUILD_NUMBER>
</properties>
</project>

View File

@ -1,68 +0,0 @@
package me.asofold.bpl.cncp.hooks.generic;
import java.util.Arrays;
import me.asofold.bpl.cncp.CompatNoCheatPlus;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.components.registry.order.RegistrationOrder.RegisterMethodWithOrder;
/**
* Wrap block break events to exempt players from checks by comparison of event class names.
* @author mc_dev
*
*/
public class HookBlockBreak extends ClassExemptionHook implements Listener {
public HookBlockBreak() {
super("block-break.");
defaultClasses.addAll(Arrays.asList(new String[]{
// MachinaCraft
"ArtificialBlockBreakEvent",
// mcMMO
"FakeBlockBreakEvent",
// MagicSpells
"MagicSpellsBlockBreakEvent"
}));
}
@Override
public String getHookName() {
return "BlockBreak(default)";
}
@Override
public String getHookVersion() {
return "1.1";
}
@Override
public Listener[] getListeners() {
return new Listener[]{this};
}
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
super.applyConfig(cfg, prefix);
if (classes.isEmpty()) enabled = false;
}
@EventHandler(priority = EventPriority.LOWEST)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagEarlyFeature, beforeTag = CompatNoCheatPlus.beforeTagEarlyFeature)
public final void onBlockBreakLowest(final BlockBreakEvent event){
checkExempt(event.getPlayer(), event.getClass(), CheckType.BLOCKBREAK);
}
@EventHandler(priority = EventPriority.MONITOR)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagLateFeature, afterTag = CompatNoCheatPlus.afterTagLateFeature)
public final void onBlockBreakMonitor(final BlockBreakEvent event){
checkUnexempt(event.getPlayer(), event.getClass(), CheckType.BLOCKBREAK);
}
}

View File

@ -1,66 +0,0 @@
package me.asofold.bpl.cncp.hooks.generic;
import java.util.Arrays;
import me.asofold.bpl.cncp.CompatNoCheatPlus;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.components.registry.order.RegistrationOrder.RegisterMethodWithOrder;
/**
* Wrap block place events to exempt players from checks by comparison of event class names.
* @author mc_dev
*
*/
public class HookBlockPlace extends ClassExemptionHook implements Listener{
public HookBlockPlace() {
super("block-place.");
defaultClasses.addAll(Arrays.asList(new String[]{
// MachinaCraft
"ArtificialBlockPlaceEvent",
// MagicSpells
"MagicSpellsBlockPlaceEvent"
}));
}
@Override
public String getHookName() {
return "BlockPlace(default)";
}
@Override
public String getHookVersion() {
return "1.0";
}
@Override
public Listener[] getListeners() {
return new Listener[]{this};
}
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
super.applyConfig(cfg, prefix);
if (classes.isEmpty()) enabled = false;
}
@EventHandler(priority = EventPriority.LOWEST)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagEarlyFeature, beforeTag = CompatNoCheatPlus.beforeTagEarlyFeature)
public final void onBlockPlaceLowest(final BlockPlaceEvent event){
checkExempt(event.getPlayer(), event.getClass(), CheckType.BLOCKPLACE);
}
@EventHandler(priority = EventPriority.MONITOR)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagLateFeature, afterTag = CompatNoCheatPlus.afterTagLateFeature)
public final void onBlockPlaceMonitor(final BlockPlaceEvent event){
checkUnexempt(event.getPlayer(), event.getClass(), CheckType.BLOCKPLACE);
}
}

View File

@ -1,70 +0,0 @@
package me.asofold.bpl.cncp.hooks.generic;
import java.util.Arrays;
import me.asofold.bpl.cncp.CompatNoCheatPlus;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.components.registry.order.RegistrationOrder.RegisterMethodWithOrder;
public class HookEntityDamageByEntity extends ClassExemptionHook implements
Listener {
public HookEntityDamageByEntity() {
super("entity-damage-by-entity.");
defaultClasses.addAll(Arrays.asList(new String[] {
// CrackShot
"WeaponDamageEntityEvent",
// MagicSpells
"MagicSpellsEntityDamageByEntityEvent" }));
}
@Override
public String getHookName() {
return "EntityDamageByEntity(default)";
}
@Override
public String getHookVersion() {
return "0.0";
}
@Override
public Listener[] getListeners() {
return new Listener[] { this };
}
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
super.applyConfig(cfg, prefix);
if (classes.isEmpty())
enabled = false;
}
@EventHandler(priority = EventPriority.LOWEST)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagEarlyFeature, beforeTag = CompatNoCheatPlus.beforeTagEarlyFeature)
public final void onDamageLowest(final EntityDamageByEntityEvent event) {
final Entity damager = event.getDamager();
if (damager instanceof Player) {
checkExempt((Player) damager, event.getClass(), CheckType.FIGHT);
}
}
@EventHandler(priority = EventPriority.MONITOR)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagLateFeature, afterTag = CompatNoCheatPlus.afterTagLateFeature)
public final void onDamageMonitor(final EntityDamageByEntityEvent event) {
final Entity damager = event.getDamager();
if (damager instanceof Player) {
checkUnexempt((Player) damager, event.getClass(), CheckType.FIGHT);
}
}
}

View File

@ -1,176 +0,0 @@
package me.asofold.bpl.cncp.hooks.generic;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import me.asofold.bpl.cncp.CompatNoCheatPlus;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfigFactory;
import me.asofold.bpl.cncp.config.compatlayer.ConfigUtil;
import me.asofold.bpl.cncp.hooks.AbstractHook;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockDamageEvent;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.components.registry.order.RegistrationOrder.RegisterMethodWithOrder;
import fr.neatmonster.nocheatplus.utilities.TickTask;
public class HookInstaBreak extends AbstractHook implements ConfigurableHook, Listener {
public static interface InstaExemption{
public void addExemptNext(CheckType[] types);
public Set<CheckType> getExemptNext();
}
public static class StackEntry{
public final CheckType[] checkTypes;
public final int tick;
public final Player player;
public boolean used = false;
public StackEntry(final Player player , final CheckType[] checkTypes){
this.player = player;
this.checkTypes = checkTypes;
tick = TickTask.getTick();
}
public boolean isOutdated(final int tick){
return tick != this.tick;
}
}
protected static InstaExemption runtime = null;
public static void addExemptNext(final CheckType[] types){
runtime.addExemptNext(types);
}
protected final ExemptionManager exMan = new ExemptionManager();
protected boolean enabled = true;
protected final List<StackEntry> stack = new LinkedList<StackEntry>();
@Override
public String getHookName() {
return "InstaBreak(default)";
}
@Override
public String getHookVersion() {
return "1.0";
}
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
enabled = cfg.getBoolean(prefix + "insta-break.enabled", true);
}
@Override
public boolean updateConfig(CompatConfig cfg, String prefix) {
CompatConfig defaults = CompatConfigFactory.getConfig(null);
defaults.set(prefix + "insta-break.enabled", true);
return ConfigUtil.forceDefaults(defaults, cfg);
}
@Override
public boolean isEnabled() {
return enabled;
}
@Override
public CheckType[] getCheckTypes() {
return null;
}
@Override
public Listener[] getListeners() {
runtime = new InstaExemption() {
protected final Set<CheckType> types = new HashSet<CheckType>();
@Override
public final void addExemptNext(final CheckType[] types) {
for (int i = 0; i < types.length; i++){
this.types.add(types[i]);
}
}
@Override
public Set<CheckType> getExemptNext() {
return types;
}
};
return new Listener[]{this};
}
protected CheckType[] fetchTypes(){
final Set<CheckType> types = runtime.getExemptNext();
final CheckType[] a = new CheckType[types.size()];
if (!types.isEmpty()) types.toArray(a);
types.clear();
return a;
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = false)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagLateFeature, afterTag = CompatNoCheatPlus.afterTagLateFeature)
public void onBlockDamage(final BlockDamageEvent event){
checkStack();
if (!event.isCancelled() && event.getInstaBreak()){
stack.add(new StackEntry(event.getPlayer(), fetchTypes()));
}
else{
runtime.getExemptNext().clear();
}
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = false)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagEarlyFeature, beforeTag = CompatNoCheatPlus.beforeTagEarlyFeature)
public void onBlockBreakLowest(final BlockBreakEvent event){
checkStack();
if (!stack.isEmpty()){
final Player player = event.getPlayer();
final StackEntry entry = stack.get(stack.size() - 1);
if (player.equals(entry.player)) addExemption(entry);
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = false)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagLateFeature, afterTag = CompatNoCheatPlus.afterTagLateFeature)
public void onBlockBreakMONITOR(final BlockBreakEvent event){
if (!stack.isEmpty()){
final Player player = event.getPlayer();
final StackEntry entry = stack.get(stack.size() - 1);
if (player.equals(entry.player)) removeExemption(stack.remove(stack.size() - 1));
}
}
public void addExemption(final StackEntry entry){
entry.used = true;
for (int i = 0; i < entry.checkTypes.length; i++){
exMan.addExemption(entry.player, entry.checkTypes[i]);
}
}
public void removeExemption(final StackEntry entry){
if (!entry.used) return;
for (int i = 0; i < entry.checkTypes.length; i++){
exMan.removeExemption(entry.player, entry.checkTypes[i]);
}
}
public void checkStack(){
if (stack.isEmpty()) return;
Iterator<StackEntry> it = stack.iterator();
final int tick = TickTask.getTick();
while (it.hasNext()){
final StackEntry entry = it.next();
if (entry.isOutdated(tick)) it.remove();
if (entry.used) removeExemption(entry);
}
}
}

View File

@ -1,62 +0,0 @@
package me.asofold.bpl.cncp.hooks.generic;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.components.registry.order.RegistrationOrder.RegisterMethodWithOrder;
import me.asofold.bpl.cncp.CompatNoCheatPlus;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import java.util.Arrays;
/**
* Wrap player interact events to exempt players from checks by comparison of event class names.
* Uses mc_dev's format for exemption based upon class names.
*
*/
public class HookPlayerInteract extends ClassExemptionHook implements Listener{
public HookPlayerInteract() {
super("player-interact.");
defaultClasses.addAll(Arrays.asList(new String[]{
// MagicSpells
"MagicSpellsPlayerInteractEvent"
}));
}
@Override
public String getHookName() {
return "Interact(default)";
}
@Override
public String getHookVersion() {
return "1.0";
}
@Override
public Listener[] getListeners() {
return new Listener[]{this};
}
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
super.applyConfig(cfg, prefix);
if (classes.isEmpty()) enabled = false;
}
@EventHandler(priority = EventPriority.LOWEST)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagEarlyFeature, beforeTag = CompatNoCheatPlus.beforeTagEarlyFeature)
public final void onPlayerInteractLowest(final PlayerInteractEvent event){
checkExempt(event.getPlayer(), event.getClass(), CheckType.BLOCKINTERACT);
}
@EventHandler(priority = EventPriority.MONITOR)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagLateFeature, afterTag = CompatNoCheatPlus.afterTagLateFeature)
public final void onPlayerInteractMonitor(final PlayerInteractEvent event){
checkUnexempt(event.getPlayer(), event.getClass(), CheckType.BLOCKINTERACT);
}
}

View File

@ -1,109 +0,0 @@
package me.asofold.bpl.cncp.hooks.generic;
import me.asofold.bpl.cncp.CompatNoCheatPlus;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfigFactory;
import me.asofold.bpl.cncp.config.compatlayer.ConfigUtil;
import me.asofold.bpl.cncp.hooks.AbstractHook;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.components.registry.order.RegistrationOrder.RegisterMethodWithOrder;
public class HookSetSpeed extends AbstractHook implements Listener, ConfigurableHook{
private static final float defaultFlySpeed = 0.1f;
private static final float defaultWalkSpeed = 0.2f;
protected float flySpeed = defaultFlySpeed;
protected float walkSpeed = defaultWalkSpeed;
protected boolean enabled = false;
// private String allowFlightPerm = "cncp.allow-flight";
public HookSetSpeed() throws SecurityException, NoSuchMethodException{
Player.class.getDeclaredMethod("setFlySpeed", float.class);
}
public void init(){
for (final Player player : Bukkit.getOnlinePlayers()){
setSpeed(player);
}
}
@Override
public String getHookName() {
return "SetSpeed(default)";
}
@Override
public String getHookVersion() {
return "2.2";
}
@Override
public CheckType[] getCheckTypes() {
return new CheckType[0];
}
@Override
public Listener[] getListeners() {
try{
// Initialize here, at the end of enable.
init();
}
catch (Throwable t){}
return new Listener[]{this} ;
}
public final void setSpeed(final Player player){
// if (allowFlightPerm.equals("") || player.hasPermission(allowFlightPerm)) player.setAllowFlight(true);
player.setWalkSpeed(walkSpeed);
player.setFlySpeed(flySpeed);
}
@EventHandler(priority=EventPriority.LOWEST)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagEarlyFeature, beforeTag = CompatNoCheatPlus.beforeTagEarlyFeature)
public final void onPlayerJoin(final PlayerJoinEvent event){
setSpeed(event.getPlayer());
}
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
enabled = cfg.getBoolean(prefix + "set-speed.enabled", false);
flySpeed = cfg.getDouble(prefix + "set-speed.fly-speed", (double) defaultFlySpeed).floatValue();
walkSpeed = cfg.getDouble(prefix + "set-speed.walk-speed", (double) defaultWalkSpeed).floatValue();
// allowFlightPerm = cfg.getString(prefix + "set-speed.allow-flight-permission", ref.allowFlightPerm);
}
@Override
public boolean updateConfig(CompatConfig cfg, String prefix) {
CompatConfig defaults = CompatConfigFactory.getConfig(null);
defaults.set(prefix + "set-speed.enabled", false);
defaults.set(prefix + "set-speed.fly-speed", defaultFlySpeed);
defaults.set(prefix + "set-speed.walk-speed", defaultWalkSpeed);
// cfg.set(prefix + "set-speed.allow-flight-permission", ref.allowFlightPerm);
return ConfigUtil.forceDefaults(defaults, cfg);
}
@Override
public boolean isEnabled() {
return enabled;
}
// public String getAllowFlightPerm() {
// return allowFlightPerm;
// }
// public void setAllowFlightPerm(String allowFlightPerm) {
// this.allowFlightPerm = allowFlightPerm;
// }
}

View File

@ -1,186 +0,0 @@
package me.asofold.bpl.cncp.hooks.mcmmo;
import me.asofold.bpl.cncp.CompatNoCheatPlus;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfigFactory;
import me.asofold.bpl.cncp.config.compatlayer.ConfigUtil;
import me.asofold.bpl.cncp.hooks.AbstractHook;
import me.asofold.bpl.cncp.hooks.generic.ConfigurableHook;
import me.asofold.bpl.cncp.utils.PluginGetter;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import com.gmail.nossr50.mcMMO;
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.CheckType;
import fr.neatmonster.nocheatplus.components.registry.order.RegistrationOrder.RegisterMethodWithOrder;
import fr.neatmonster.nocheatplus.hooks.NCPHook;
public final class HookmcMMO extends AbstractHook implements Listener, ConfigurableHook {
/**
* To let the listener access this.
* @author mc_dev
*
*/
public static interface HookFacade{
public void damageLowest(Player player);
public void damageMonitor(Player player);
public void blockDamageLowest(Player player);
public void blockDamageMonitor(Player player);
/**
* If to cancel the event.
* @param player
* @return
*/
public boolean blockBreakLowest(Player player);
public void blockBreakMontitor(Player player);
}
protected HookFacade ncpHook = null;
protected boolean enabled = true;
protected String configPrefix = "mcmmo.";
protected boolean useInstaBreakHook = true;
public HookmcMMO(){
assertPluginPresent("mcMMO");
}
protected final PluginGetter<mcMMO> fetch = new PluginGetter<mcMMO>("mcMMO");
protected int blocksPerSecond = 30;
@Override
public String getHookName() {
return "mcMMO(default)";
}
@Override
public String getHookVersion() {
return "2.1";
}
@Override
public CheckType[] getCheckTypes() {
return new CheckType[]{
CheckType.BLOCKBREAK_FASTBREAK, CheckType.BLOCKBREAK_NOSWING, // old ones
// CheckType.BLOCKBREAK_DIRECTION, CheckType.BLOCKBREAK_FREQUENCY,
// CheckType.BLOCKBREAK_WRONGBLOCK, CheckType.BLOCKBREAK_REACH,
//
// CheckType.FIGHT_ANGLE, CheckType.FIGHT_SPEED, // old ones
//
// CheckType.FIGHT_DIRECTION, CheckType.FIGHT_NOSWING,
// CheckType.FIGHT_REACH,
};
}
@Override
public Listener[] getListeners() {
fetch.fetchPlugin();
return new Listener[]{this, fetch};
}
@Override
public NCPHook getNCPHook() {
if (ncpHook == null){
ncpHook = new HookFacadeImpl(useInstaBreakHook, blocksPerSecond);
}
return (NCPHook) ncpHook;
}
///////////////////////////
// Damage (fight)
//////////////////////////
@EventHandler(priority=EventPriority.LOWEST)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagEarlyFeature, beforeTag = CompatNoCheatPlus.beforeTagEarlyFeature)
public final void onDamageLowest(final FakeEntityDamageByEntityEvent event){
final Entity entity = event.getDamager();
if (entity instanceof Player)
ncpHook.damageLowest((Player) entity);
}
@EventHandler(priority=EventPriority.MONITOR)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagLateFeature, afterTag = CompatNoCheatPlus.afterTagLateFeature)
public final void onDamageMonitor(final FakeEntityDamageByEntityEvent event){
final Entity entity = event.getDamager();
if (entity instanceof Player)
ncpHook.damageMonitor((Player) entity);
}
///////////////////////////
// Block damage
//////////////////////////
@EventHandler(priority=EventPriority.LOWEST)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagEarlyFeature, beforeTag = CompatNoCheatPlus.beforeTagEarlyFeature)
public final void onBlockDamageLowest(final FakeBlockDamageEvent event){
ncpHook.blockDamageLowest(event.getPlayer());
}
@EventHandler(priority=EventPriority.LOWEST)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagEarlyFeature, beforeTag = CompatNoCheatPlus.beforeTagEarlyFeature)
public final void onBlockDamageMonitor(final FakeBlockDamageEvent event){
ncpHook.blockDamageMonitor(event.getPlayer());
}
///////////////////////////
// Block break
//////////////////////////
@EventHandler(priority=EventPriority.LOWEST)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagEarlyFeature, beforeTag = CompatNoCheatPlus.beforeTagEarlyFeature)
public final void onBlockBreakLowest(final FakeBlockBreakEvent event){
if (ncpHook.blockBreakLowest(event.getPlayer())){
event.setCancelled(true);
// System.out.println("Cancelled for frequency.");
}
}
@EventHandler(priority=EventPriority.MONITOR)
@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagLateFeature, afterTag = CompatNoCheatPlus.afterTagLateFeature)
public final void onBlockBreakLMonitor(final FakeBlockBreakEvent event){
ncpHook.blockBreakMontitor(event.getPlayer());
}
/////////////////////////////////
// Config
/////////////////////////////////
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
enabled = cfg.getBoolean(prefix + configPrefix + "enabled", true);
useInstaBreakHook = cfg.getBoolean(prefix + configPrefix + "use-insta-break-hook", true);
blocksPerSecond = cfg.getInt(prefix + configPrefix + "clickspersecond", 20);
}
@Override
public boolean updateConfig(CompatConfig cfg, String prefix) {
CompatConfig defaults = CompatConfigFactory.getConfig(null);
defaults.set(prefix + configPrefix + "enabled", true);
defaults.set(prefix + configPrefix + "use-insta-break-hook", true);
defaults.set(prefix + configPrefix + "clickspersecond", 20);
return ConfigUtil.forceDefaults(defaults, cfg);
}
@Override
public boolean isEnabled() {
return enabled;
}
}

4
README.md Normal file
View File

@ -0,0 +1,4 @@
CompatNoCheatPlus
---------
CompatNoCheatPlus (cncp) provides compatibility between the anti cheat plugin NoCheatPlus and other plugins that add game mechanics different to the vanilla game behavior, such as mcMMO or plugins that add npcs such as Citizens and protocol hack like Geyser for cross-platform to play with.

4
bungee.yml Normal file
View File

@ -0,0 +1,4 @@
name: CompatNoCheatPlus
main: me.asofold.bpl.cncp.bungee.CompatNoCheatPlus
version: ${project.version}-${buildDescription}
author: asofold, xaw3ep

BIN
libs/CMIAPI7.6.2.0.jar Normal file

Binary file not shown.

BIN
libs/GravityTubes.jar Normal file

Binary file not shown.

BIN
libs/mcMMO-2.1.158.jar Normal file

Binary file not shown.

View File

@ -1,9 +1,11 @@
name: CompatNoCheatPlus
main: me.asofold.bpl.cncp.CompatNoCheatPlus
version: ${project.version}-s${BUILD_SERIES}-b${BUILD_NUMBER}
version: ${project.version}-${buildDescription}
dev-url: http://dev.bukkit.org/server-mods/compatnocheatplus-cncp/
api-version: 1.13
folia-supported: true
depend:
loadbefore:
- NoCheatPlus
softdepend:
- mcMMO

187
pom.xml Normal file
View File

@ -0,0 +1,187 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>CompatNoCheatPlus</groupId>
<artifactId>CompatNoCheatPlus</artifactId>
<version>6.6.7-SNAPSHOT</version>
<name>CompatNoCheatPlus</name>
<!-- Source code -->
<scm>
<developerConnection>scm:git:git@github.com:asofold/${project.name}.git</developerConnection>
<connection>scm:git:git://github.com/asofold/${project.name}.git</connection>
<url>https://github.com/asofold/${project.name}</url>
</scm>
<!-- Repositories -->
<repositories>
<repository>
<id>opencollab-snapshot-repo</id>
<url>https://repo.opencollab.dev/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<repository>
<id>viaversion-repo</id>
<url>https://repo.viaversion.com</url>
</repository>
<repository>
<id>bungeecord-repo</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
</repositories>
<!-- Dependencies -->
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.8.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.gmail.nossr50.mcMMO</groupId>
<artifactId>mcMMO</artifactId>
<version>2.1.158</version>
<scope>system</scope>
<systemPath>${basedir}/libs/mcMMO-2.1.158.jar</systemPath>
</dependency>
<dependency>
<groupId>net.citizensnpcs</groupId>
<artifactId>citizensapi</artifactId>
<version>2.0.26-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.benzoft.gravitytubes</groupId>
<artifactId>gravitytubes</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/libs/GravityTubes.jar</systemPath>
</dependency>
<dependency>
<groupId>com.Zrips.CMI</groupId>
<artifactId>CMI</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/libs/CMIAPI7.6.2.0.jar</systemPath>
</dependency>
<dependency>
<groupId>com.github.updated-nocheatplus.nocheatplus</groupId>
<artifactId>nocheatplus</artifactId>
<version>-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>connector</artifactId>
<version>1.4.2-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.geysermc.floodgate</groupId>
<artifactId>api</artifactId>
<version>2.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.19-R0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.viaversion</groupId>
<artifactId>viaversion-api</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-event</artifactId>
<version>1.19-R0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<!-- Build Description Profiles -->
<profiles>
<profile>
<id>timestamp</id>
<activation>
<property>
<name>!env.BUILD_NUMBER</name>
</property>
</activation>
<properties>
<buildDescription>${maven.build.timestamp}</buildDescription>
</properties>
</profile>
<profile>
<id>dynamic_build_number</id>
<activation>
<property>
<name>env.BUILD_NUMBER</name>
</property>
</activation>
<properties>
<buildDescription>b${env.BUILD_NUMBER}</buildDescription>
</properties>
</profile>
</profiles>
<!-- Building -->
<build>
<defaultGoal>clean package</defaultGoal>
<sourceDirectory>${basedir}/src</sourceDirectory>
<resources>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>${basedir}</directory>
<includes>
<include>plugin.yml</include>
<include>LICENSE.txt</include>
<include>bungee.yml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<finalName>cncp</finalName>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
<pomPropertiesFile>false</pomPropertiesFile>
<manifest>
<addDefaultSpecificationEntries>false</addDefaultSpecificationEntries>
<addDefaultImplementationEntries>false</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<!-- Properties -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.build.timestamp.format>yyyy_MM_dd-HH_mm</maven.build.timestamp.format>
</properties>
</project>

View File

@ -0,0 +1,50 @@
package me.asofold.bpl.cncp.ClientVersion;
import java.lang.reflect.Method;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.Plugin;
import com.viaversion.viaversion.api.Via;
import fr.neatmonster.nocheatplus.compat.Folia;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import me.asofold.bpl.cncp.CompatNoCheatPlus;
public class ClientVersionListener implements Listener {
private Plugin ViaVersion = Bukkit.getPluginManager().getPlugin("ViaVersion");
private Plugin ProtocolSupport = Bukkit.getPluginManager().getPlugin("ProtocolSupport");
private final Class<?> ProtocolSupportAPIClass = ReflectionUtil.getClass("protocolsupport.api.ProtocolSupportAPI");
private final Class<?> ProtocolVersionClass = ReflectionUtil.getClass("protocolsupport.api.ProtocolVersion");
private final Method getProtocolVersion = ProtocolSupportAPIClass == null ? null : ReflectionUtil.getMethod(ProtocolSupportAPIClass, "getProtocolVersion", Player.class);
@SuppressWarnings("unchecked")
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerJoin(PlayerJoinEvent event) {
final Player player = event.getPlayer();
Folia.runSyncDelayedTask(CompatNoCheatPlus.getInstance(), (arg) -> {
final IPlayerData pData = DataManager.getPlayerData(player);
if (pData != null) {
if (ViaVersion != null && ViaVersion.isEnabled()) {
// Give precedence to ViaVersion
pData.setClientVersionID(Via.getAPI().getPlayerVersion(player));
}
else if (ProtocolSupport != null && getProtocolVersion != null && ProtocolSupport.isEnabled()) {
// Fallback to PS (reflectively, due to PS not having a valid mvn repo)
Object protocolVersion = ReflectionUtil.invokeMethod(getProtocolVersion, null, player);
Method getId = ReflectionUtil.getMethodNoArgs(ProtocolVersionClass, "getId", int.class);
int version = (int) ReflectionUtil.invokeMethodNoArgs(getId, protocolVersion);
pData.setClientVersionID(version);
}
// (Client version stays unknown (-1))
}
}, 20); // Wait 20 ticks before setting client data
}
}

View File

@ -2,25 +2,34 @@ package me.asofold.bpl.cncp;
import java.io.File;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitScheduler;
import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.compat.Folia;
import fr.neatmonster.nocheatplus.components.registry.feature.IDisableListener;
import fr.neatmonster.nocheatplus.components.registry.order.RegistrationOrder;
import fr.neatmonster.nocheatplus.hooks.NCPHook;
import fr.neatmonster.nocheatplus.hooks.NCPHookManager;
import me.asofold.bpl.cncp.bedrock.BedrockPlayerListener;
import me.asofold.bpl.cncp.ClientVersion.ClientVersionListener;
import me.asofold.bpl.cncp.config.Settings;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import me.asofold.bpl.cncp.config.compatlayer.NewConfig;
@ -33,45 +42,21 @@ import me.asofold.bpl.cncp.hooks.generic.HookInstaBreak;
import me.asofold.bpl.cncp.hooks.generic.HookPlayerClass;
import me.asofold.bpl.cncp.hooks.generic.HookPlayerInteract;
import me.asofold.bpl.cncp.utils.TickTask2;
import me.asofold.bpl.cncp.utils.Utils;
/**
* Quick attempt to provide compatibility to NoCheatPlus (by NeatMonster) for
* some other plugins that change the vanilla game mechanichs, for instance by
* fast block breaking.
*
* @author asofold
* Quick attempt to provide compatibility to NoCheatPlus (by NeatMonster) for some other plugins that change the vanilla game mechanichs, for instance by fast block breaking.
* @author mc_dev
*
*/
public class CompatNoCheatPlus extends JavaPlugin {
public class CompatNoCheatPlus extends JavaPlugin implements Listener {
//TODO: Adjust, once NCP has order everywhere (generic + ncp-specific?).
public static final String tagEarlyFeature = "cncp.feature.early";
public static final String beforeTagEarlyFeature = ".*nocheatplus.*|.*NoCheatPlus.*";
public static final String tagLateFeature = "cncp.feature.late";
public static final String afterTagLateFeature = "cncp.system.early.*|.*nocheatplus.*|.*NoCheatPlus.*)";
public static final String tagEarlySystem = "cncp.system.early";
public static final String beforeTagEarlySystem = beforeTagEarlyFeature; // ...
public static final RegistrationOrder defaultOrderSystemEarly = new RegistrationOrder(
tagEarlySystem,
beforeTagEarlySystem,
null);
public static final RegistrationOrder defaultOrderFeatureEarly = new RegistrationOrder(
tagEarlyFeature,
beforeTagEarlyFeature,
"cncp.system.early.*");
public static final RegistrationOrder defaultOrderFeatureLate = new RegistrationOrder(
tagLateFeature,
null,
afterTagLateFeature);
private static CompatNoCheatPlus instance = null;
private final Settings settings = new Settings();
private boolean bungee;
/** Hooks registered with cncp */
private static final Set<Hook> registeredHooks = new HashSet<Hook>();
@ -82,6 +67,15 @@ public class CompatNoCheatPlus extends JavaPlugin {
*/
private static boolean enabled = false;
/**
* Experimental: static method to enable this plugin, only enables if it is not already enabled.
* @return
*/
public static boolean enableCncp(){
if (enabled) return true;
return enablePlugin("CompatNoCheatPlus");
}
/**
* Static method to enable a plugin (might also be useful for hooks).
* @param plgName
@ -115,7 +109,7 @@ public class CompatNoCheatPlus extends JavaPlugin {
* @return
*/
public static CompatNoCheatPlus getInstance(){
return CompatNoCheatPlus.getPlugin(CompatNoCheatPlus.class);
return instance;
}
/**
@ -126,13 +120,13 @@ public class CompatNoCheatPlus extends JavaPlugin {
*/
public static boolean addHook(Hook hook){
if (Settings.preventAddHooks.contains(hook.getHookName())){
Bukkit.getLogger().info("[cncp] Prevented adding hook: "+hook.getHookName() + " / " + hook.getHookVersion());
Bukkit.getLogger().info("[CompatNoCheatPlus] Prevented adding hook: "+hook.getHookName() + " / " + hook.getHookVersion());
return false;
}
registeredHooks.add(hook);
if (enabled) registerListeners(hook);
boolean added = checkAddNCPHook(hook); // Add if plugin is present, otherwise queue for adding.
Bukkit.getLogger().info("[cncp] Registered hook"+(added?"":"(NCPHook might get added later)")+": "+hook.getHookName() + " / " + hook.getHookVersion());
Bukkit.getLogger().info("[CompatNoCheatPlus] Registered hook"+(added?"":"(NCPHook might get added later)")+": "+hook.getHookName() + " / " + hook.getHookVersion());
return true;
}
@ -158,26 +152,20 @@ public class CompatNoCheatPlus extends JavaPlugin {
* @return
*/
public static boolean registerListeners(Hook hook) {
if (!enabled) {
return false;
}
if (!enabled) return false;
Listener[] listeners = hook.getListeners();
if (listeners != null){
// attempt to register events:
Plugin plg = CompatNoCheatPlus.getPlugin(CompatNoCheatPlus.class);
if (plg == null) {
return false;
}
PluginManager pm = Bukkit.getPluginManager();
Plugin plg = pm.getPlugin("CompatNoCheatPlus");
if (plg == null) return false;
for (Listener listener : listeners) {
NCPAPIProvider.getNoCheatPlusAPI().getEventRegistry().register(listener,
defaultOrderFeatureEarly, plg);
pm.registerEvents(listener, plg);
}
}
return true;
}
// ----
/**
* Called before loading settings, adds available hooks into a list, so they will be able to read config.
*/
@ -199,6 +187,16 @@ public class CompatNoCheatPlus extends JavaPlugin {
builtinHooks.add(new me.asofold.bpl.cncp.hooks.mcmmo.HookmcMMO());
}
catch (Throwable t) {}
// GravityTubes
try {
builtinHooks.add(new me.asofold.bpl.cncp.hooks.GravityTubes.HookGravityTubes());
}
catch (Throwable t) {}
// CMI
try {
builtinHooks.add(new me.asofold.bpl.cncp.hooks.CMI.HookCMI());
}
catch (Throwable t){}
// // MagicSpells
// try{
// builtinHooks.add(new me.asofold.bpl.cncp.hooks.magicspells.HookMagicSpells());
@ -240,6 +238,7 @@ public class CompatNoCheatPlus extends JavaPlugin {
@Override
public void onEnable() {
enabled = false; // make sure
instance = this;
// (no cleanup)
// Settings:
@ -247,7 +246,21 @@ public class CompatNoCheatPlus extends JavaPlugin {
setupBuiltinHooks();
loadSettings();
// Register own listener:
//NCPAPIProvider.getNoCheatPlusAPI().getEventRegistry().register(this, defaultOrderSystemEarly, this);
final PluginManager pm = getServer().getPluginManager();
pm.registerEvents(this, this);
pm.registerEvents(new BedrockPlayerListener(), this);
pm.registerEvents(new ClientVersionListener(), this);
getServer().getMessenger().registerIncomingPluginChannel(this, "cncp:geyser", new BedrockPlayerListener());
try {
bungee = getServer().spigot().getConfig().getBoolean("settings.bungeecord");
// sometimes not work, try the hard way
if (!bungee) {
bungee = YamlConfiguration.loadConfiguration(new File("spigot.yml")).getBoolean("settings.bungeecord");
}
} catch (Throwable t) {
bungee = false;
}
super.onEnable();
// Add Hooks:
@ -259,36 +272,32 @@ public class CompatNoCheatPlus extends JavaPlugin {
registerListeners(hook);
}
// Register to remove hooks when NCP is disabling.
NCPAPIProvider.getNoCheatPlusAPI().addComponent(new IDisableListener(){
@Override
public void onDisable() {
// Remove all registered cncp hooks:
unregisterNCPHooks();
}
});
if (!registeredHooks.isEmpty()) {
registerHooks();
}
// Start ticktask 2
// TODO: Replace by using TickTask ? Needs order (depend is used now)?
getServer().getScheduler().scheduleSyncRepeatingTask(this, new TickTask2(), 1, 1);
Folia.runSyncRepatingTask(this, (arg) -> new TickTask2().run(), 1, 1);
// Check for the NoCheatPlus plugin.
Plugin plugin = pm.getPlugin("NoCheatPlus");
if (plugin == null) {
getLogger().severe("[CompatNoCheatPlus] The NoCheatPlus plugin is not present.");
}
else if (plugin.isEnabled()) {
getLogger().severe("[CompatNoCheatPlus] The NoCheatPlus plugin already is enabled, this might break several hooks.");
}
// Finished.
getLogger().info(getDescription().getFullName() + " is enabled. Some hooks might get registered with NoCheatPlus later on.");
}
public boolean loadSettings() {
final Set<String> oldForceEnableLater = new LinkedHashSet<String>();
oldForceEnableLater.addAll(settings.forceEnableLater);
// Read and apply config to settings:
File file = new File(getDataFolder() , "cncp.yml");
CompatConfig cfg = new NewConfig(file);
cfg.load();
boolean changed = false;
// General settings:
if (Settings.addDefaults(cfg)) {
changed = true;
}
if (Settings.addDefaults(cfg)) changed = true;
settings.fromConfig(cfg);
// Settings for builtin hooks:
for (Hook hook : builtinHooks){
@ -299,14 +308,57 @@ public class CompatNoCheatPlus extends JavaPlugin {
cfgHook.applyConfig(cfg, "hooks.");
}
catch (Throwable t){
getLogger().severe("[cncp] Hook failed to process config ("+hook.getHookName() +" / " + hook.getHookVersion()+"): " + t.getClass().getSimpleName() + ": "+t.getMessage());
getLogger().severe("[CompatNoCheatPlus] Hook failed to process config ("+hook.getHookName() +" / " + hook.getHookVersion()+"): " + t.getClass().getSimpleName() + ": "+t.getMessage());
t.printStackTrace();
}
}
}
// save back config if changed:
if (changed) {
cfg.save();
if (changed) cfg.save();
// Re-enable plugins that were not yet on the list:
Server server = getServer();
Logger logger = server.getLogger();
for (String plgName : settings.loadPlugins){
try{
if (CompatNoCheatPlus.enablePlugin(plgName)){
System.out.println("[CompatNoCheatPlus] Ensured that the following plugin is enabled: " + plgName);
}
}
catch (Throwable t){
logger.severe("[CompatNoCheatPlus] Failed to enable the plugin: " + plgName);
logger.severe(Utils.toString(t));
}
}
BukkitScheduler sched = server.getScheduler();
for (String plgName : settings.forceEnableLater){
if (!oldForceEnableLater.remove(plgName)) oldForceEnableLater.add(plgName);
}
if (!oldForceEnableLater.isEmpty()){
System.out.println("[CompatNoCheatPlus] Schedule task to re-enable plugins later...");
sched.scheduleSyncDelayedTask(this, new Runnable() {
@Override
public void run() {
// (Later maybe re-enabling this plugin could be added.)
// TODO: log levels !
for (String plgName : oldForceEnableLater){
try{
if (disablePlugin(plgName)){
if (enablePlugin(plgName)) System.out.println("[CompatNoCheatPlus] Re-enabled plugin: " + plgName);
else System.out.println("[CompatNoCheatPlus] Could not re-enable plugin: "+plgName);
}
else{
System.out.println("[CompatNoCheatPlus] Could not disable plugin (already disabled?): "+plgName);
}
}
catch (Throwable t){
// TODO: maybe log ?
}
}
}
});
}
return true;
@ -316,6 +368,8 @@ public class CompatNoCheatPlus extends JavaPlugin {
public void onDisable() {
unregisterNCPHooks(); // Just in case.
enabled = false;
instance = null; // Set last.
getServer().getMessenger().unregisterIncomingPluginChannel(this, "cncp:geyser");
super.onDisable();
}
@ -339,7 +393,7 @@ public class CompatNoCheatPlus extends JavaPlugin {
}
}
}
getLogger().info("[cncp] Removed "+n+" registered hooks from NoCheatPlus.");
getLogger().info("[CompatNoCheatPlus] Removed "+n+" registered hooks from NoCheatPlus.");
registeredHooks.clear();
return n;
}
@ -353,10 +407,30 @@ public class CompatNoCheatPlus extends JavaPlugin {
NCPHookManager.addHook(hook.getCheckTypes(), ncpHook);
n ++;
}
getLogger().info("[cncp] Added "+n+" registered hooks to NoCheatPlus.");
getLogger().info("[CompatNoCheatPlus] Added "+n+" registered hooks to NoCheatPlus.");
return n;
}
@EventHandler(priority = EventPriority.NORMAL)
void onPluginEnable(PluginEnableEvent event){
Plugin plugin = event.getPlugin();
if (!plugin.getName().equals("NoCheatPlus")) {
return;
}
// Register to remove hooks when NCP is disabling.
NCPAPIProvider.getNoCheatPlusAPI().addComponent(new IDisableListener(){
@Override
public void onDisable() {
// Remove all registered cncp hooks:
unregisterNCPHooks();
}
});
if (registeredHooks.isEmpty()) {
return;
}
registerHooks();
}
/* (non-Javadoc)
* @see org.bukkit.plugin.java.JavaPlugin#onCommand(org.bukkit.command.CommandSender, org.bukkit.command.Command, java.lang.String, java.lang.String[])
*/
@ -384,8 +458,7 @@ public class CompatNoCheatPlus extends JavaPlugin {
infos.add(temp.isEmpty() ? "NoCheatPlus is missing or not yet enabled." : temp);
infos.add("#### Typical plugin dependencies ####");
for (String pluginName : new String[]{
"mcMMO", "Citizens", "MachinaCraft", "MagicSpells",
// TODO: extend
"mcMMO", "Citizens", "MachinaCraft", "MagicSpells", "ViaVersion", "ProtocolSupport", "GravityTubes", "Geyser-Spigot", "floodgate", "CMI", "Geyser-BungeeCord"
}){
temp = getOtherVersion(pluginName);
if (!temp.isEmpty()) infos.add(temp);
@ -420,4 +493,11 @@ public class CompatNoCheatPlus extends JavaPlugin {
return pdf.getFullName();
}
public Settings getSettings() {
return settings;
}
public boolean isBungeeEnabled() {
return bungee;
}
}

View File

@ -0,0 +1,72 @@
package me.asofold.bpl.cncp.bedrock;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.messaging.PluginMessageListener;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.floodgate.api.FloodgateApi;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import me.asofold.bpl.cncp.CompatNoCheatPlus;
import me.asofold.bpl.cncp.config.Settings;
public class BedrockPlayerListener implements Listener, PluginMessageListener {
private Plugin floodgate = Bukkit.getPluginManager().getPlugin("floodgate");
private Plugin geyser = Bukkit.getPluginManager().getPlugin("Geyser-Spigot");
private final Settings settings = CompatNoCheatPlus.getInstance().getSettings();
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerJoin(PlayerJoinEvent event) {
final Player player = event.getPlayer();
if (floodgate != null && floodgate.isEnabled()) {
if (FloodgateApi.getInstance().isFloodgatePlayer(player.getUniqueId())) {
processExemption(player);
}
}
else if (geyser != null && geyser.isEnabled()) {
try {
GeyserSession session = GeyserConnector.getInstance().getPlayerByUuid(player.getUniqueId());
if (session != null) processExemption(player);
}
catch (NullPointerException e) {}
}
}
private void processExemption(final Player player) {
final IPlayerData pData = DataManager.getPlayerData(player);
if (pData != null) {
for (CheckType check : settings.extemptChecks) pData.exempt(check);
pData.setBedrockPlayer(true);
}
}
private void processExemption(final String playername) {
final IPlayerData pData = DataManager.getPlayerData(playername);
if (pData != null) {
for (CheckType check : settings.extemptChecks) pData.exempt(check);
pData.setBedrockPlayer(true);
}
}
@Override
public void onPluginMessageReceived(String channel, Player player, byte[] data) {
if (CompatNoCheatPlus.getInstance().isBungeeEnabled() && channel.equals("cncp:geyser")) {
geyser = null;
floodgate = null;
ByteArrayDataInput input = ByteStreams.newDataInput(data);
String playerName = input.readUTF();
processExemption(playerName);
}
}
}

View File

@ -0,0 +1,86 @@
package me.asofold.bpl.cncp.bungee;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.floodgate.api.FloodgateApi;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.event.PluginMessageEvent;
import net.md_5.bungee.api.event.ServerSwitchEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.event.EventHandler;
public class CompatNoCheatPlus extends Plugin implements Listener {
private boolean floodgate;
private boolean geyser;
@Override
public void onEnable() {
geyser = checkGeyser();
floodgate = checkFloodgate();
getLogger().info("Registering listeners");
getProxy().getPluginManager().registerListener(this, this);
getProxy().registerChannel("cncp:geyser");
getLogger().info("cncp Bungee mode with Geyser : " + geyser + ", Floodgate : " + floodgate);
}
@EventHandler
public void onMessageReceive(PluginMessageEvent event) {
if (event.getTag().equalsIgnoreCase("cncp:geyser")) {
// Message sent from client, cancel it
if (event.getSender() instanceof ProxiedPlayer) {
event.setCancelled(true);
}
}
}
private boolean checkFloodgate() {
return ProxyServer.getInstance().getPluginManager().getPlugin("floodgate") != null;
}
private boolean checkGeyser() {
return ProxyServer.getInstance().getPluginManager().getPlugin("Geyser-BungeeCord") != null;
}
@SuppressWarnings("deprecation")
private boolean isBedrockPlayer(ProxiedPlayer player) {
if (floodgate) {
return FloodgateApi.getInstance().isFloodgatePlayer(player.getUniqueId());
}
if (geyser) {
try {
GeyserSession session = GeyserConnector.getInstance().getPlayerByUuid(player.getUniqueId());
return session != null;
} catch (NullPointerException e) {
return false;
}
}
return false;
}
@EventHandler
public void onChangeServer(ServerSwitchEvent event) {
ProxiedPlayer player = event.getPlayer();
Server server = player.getServer();
if (!isBedrockPlayer(player)) return;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
try {
dataOutputStream.writeUTF(player.getName());
} catch (IOException e) {
e.printStackTrace();
}
getProxy().getScheduler().schedule(this, () -> {
server.sendData("cncp:geyser", outputStream.toByteArray());
}, 1L, TimeUnit.SECONDS);
}
}

View File

@ -1,17 +1,23 @@
package me.asofold.bpl.cncp.config;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Set;
import org.bukkit.Bukkit;
import fr.neatmonster.nocheatplus.checks.CheckType;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import me.asofold.bpl.cncp.config.compatlayer.ConfigUtil;
import me.asofold.bpl.cncp.config.compatlayer.NewConfig;
public class Settings {
public static final int configVersion = 3;
public static final int configVersion = 2;
public Set<String> forceEnableLater = new LinkedHashSet<String>();
public Set<String> loadPlugins = new LinkedHashSet<String>();
public Set<CheckType> extemptChecks = new LinkedHashSet<CheckType>();
public static Set<String> preventAddHooks = new HashSet<String>();
@ -19,6 +25,20 @@ public class Settings {
CompatConfig cfg = new NewConfig(null);
cfg.set("plugins.force-enable-later", new LinkedList<String>()); // ConfigUtil.asList(new String[]{ "NoCheatPlus" }));
cfg.set("plugins.ensure-enable", new LinkedList<String>()); // ConfigUtil.asList(new String[]{ "WorldGuard" }));
cfg.set("plugins.bedrock-extempt-checks", ConfigUtil.asList(new String[]{
"ALL",
"BLOCKINTERACT_VISIBLE",
"BLOCKINTERACT_DIRECTION",
"BLOCKINTERACT_REACH",
"BLOCKBREAK_DIRECTION",
"BLOCKBREAK_NOSWING",
"BLOCKBREAK_REACH",
"BLOCKPLACE_NOSWING",
"BLOCKPLACE_DIRECTION",
"BLOCKPLACE_REACH",
"BLOCKPLACE_SCAFFOLD",
"FIGHT_DIRECTION",
}));
cfg.set("hooks.prevent-add", new LinkedList<String>());
cfg.set("configversion", configVersion);
return cfg;
@ -35,12 +55,12 @@ public class Settings {
if (cfg.getDouble("hooks.set-speed.fly-speed", 0.1) != 0.1){
changed = true;
cfg.set("hooks.set-speed.fly-speed", 0.1);
Bukkit.getLogger().warning("[cncp] Reset fly-speed for the set-speed hook to 0.1 (default) as a safety measure.");
Bukkit.getLogger().warning("[CompatNoCheatPlus] Reset fly-speed for the set-speed hook to 0.1 (default) as a safety measure.");
}
if (cfg.getDouble("hooks.set-speed.walk-speed", 0.2) != 0.2){
changed = true;
cfg.set("hooks.set-speed.walk-speed", 0.2);
Bukkit.getLogger().warning("[cncp] Reset walk-speed for the set-speed hook to 0.2 (default) as a safety measure.");
Bukkit.getLogger().warning("[CompatNoCheatPlus] Reset walk-speed for the set-speed hook to 0.2 (default) as a safety measure.");
}
}
if (ConfigUtil.forceDefaults(getDefaultConfig(), cfg)) changed = true;
@ -54,6 +74,11 @@ public class Settings {
public boolean fromConfig(CompatConfig cfg){
// Settings ref = new Settings();
// plugins to force enabling after this plugin.
ConfigUtil.readStringSetFromList(cfg, "plugins.force-enable-later", forceEnableLater, true, true, false);
ConfigUtil.readStringSetFromList(cfg, "plugins.ensure-enable", loadPlugins, true, true, false);
ConfigUtil.readCheckTypeSetFromList(cfg, "plugins.bedrock-extempt-checks", extemptChecks, true, true, true);
// General
ConfigUtil.readStringSetFromList(cfg, "hooks.prevent-add", preventAddHooks, true, true, false);
@ -61,7 +86,7 @@ public class Settings {
}
public void clear() {
// TODO: clear something !?
forceEnableLater.clear();
}
}

View File

@ -5,6 +5,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import fr.neatmonster.nocheatplus.checks.CheckType;
public class ConfigUtil {
public static final int canaryInt = Integer.MIN_VALUE +7;
@ -115,6 +117,32 @@ public class ConfigUtil {
}
}
/**
* Add StringList entries to a set.
* @param cfg
* @param path
* @param set
* @param clear If to clear the set.
* @param trim
* @param upperCase
*/
public static void readCheckTypeSetFromList(CompatConfig cfg, String path, Set<CheckType> set, boolean clear, boolean trim, boolean upperCase){
if (clear) set.clear();
List<String> tempList = cfg.getStringList(path , null);
if (tempList != null){
for (String entry : tempList) {
if (trim) entry = entry.trim();
if (upperCase) entry = entry.toUpperCase();
try {
final CheckType checkType = CheckType.valueOf(entry);
set.add(checkType);
} catch (Exception e) {
System.out.println("[CompatNoCheatPlus] Unknown check " + entry + ". Skipping.");
}
}
}
}
/**
* Return an ArrayList.
* @param input

View File

@ -0,0 +1,142 @@
package me.asofold.bpl.cncp.hooks.CMI;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import com.Zrips.CMI.CMI;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.IViolationInfo;
import fr.neatmonster.nocheatplus.hooks.NCPHook;
import me.asofold.bpl.cncp.CompatNoCheatPlus;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfigFactory;
import me.asofold.bpl.cncp.config.compatlayer.ConfigUtil;
import me.asofold.bpl.cncp.hooks.AbstractHook;
import me.asofold.bpl.cncp.hooks.generic.ConfigurableHook;
import me.asofold.bpl.cncp.hooks.generic.ExemptionManager;
import me.asofold.bpl.cncp.utils.TickTask2;
public class HookCMI extends AbstractHook implements Listener, ConfigurableHook {
protected Object ncpHook = null;
protected boolean enabled = true;
protected String configPrefix = "cmi.";
protected final ExemptionManager exMan = new ExemptionManager();
protected final CheckType[] exemptBreakMany = new CheckType[]{
CheckType.BLOCKBREAK, CheckType.COMBINED_IMPROBABLE,
};
protected final CheckType[] exemptPlaceMany = new CheckType[]{
CheckType.BLOCKPLACE, CheckType.COMBINED_IMPROBABLE,
};
public HookCMI(){
assertPluginPresent("CMI");
}
@Override
public String getHookName() {
return "CMI(default)";
}
@Override
public String getHookVersion() {
return "1.0";
}
@Override
public Listener[] getListeners() {
return new Listener[]{
this
};
}
@Override
public NCPHook getNCPHook() {
if (ncpHook == null){
ncpHook = new NCPHook() {
@Override
public String getHookName() {
return "CMI(cncp)";
}
@Override
public String getHookVersion() {
return "1.0";
}
@Override
public boolean onCheckFailure(CheckType checkType, Player player, IViolationInfo info) {
return false;
}
};
}
return (NCPHook) ncpHook;
}
@EventHandler(priority=EventPriority.MONITOR)
//@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagLateFeature, afterTag = CompatNoCheatPlus.afterTagLateFeature)
public final void onMirrorBreakMonitor(final BlockBreakEvent event){
removeExemption(event.getPlayer(), exemptBreakMany);
}
@EventHandler(priority=EventPriority.LOWEST)
//@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagEarlyFeature, beforeTag = CompatNoCheatPlus.beforeTagEarlyFeature)
public final void onMirrorBreakLowest(final BlockBreakEvent event){
if (CMI.getInstance().getMirrorManager().isMirroring(event.getPlayer())) {
addExemption(event.getPlayer(), exemptBreakMany);
}
}
@EventHandler(priority=EventPriority.MONITOR)
//@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagLateFeature, afterTag = CompatNoCheatPlus.afterTagLateFeature)
public final void onMirrorPlaceMonitor(final BlockPlaceEvent event){
removeExemption(event.getPlayer(), exemptPlaceMany);
}
@EventHandler(priority=EventPriority.LOWEST)
//@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagEarlyFeature, beforeTag = CompatNoCheatPlus.beforeTagEarlyFeature)
public final void onMirrorPlaceLowest(final BlockPlaceEvent event){
if (CMI.getInstance().getMirrorManager().isMirroring(event.getPlayer())) {
addExemption(event.getPlayer(), exemptPlaceMany);
}
}
public void addExemption(final Player player, final CheckType[] types){
for (final CheckType type : types){
exMan.addExemption(player, type);
TickTask2.addUnexemptions(player, types);
}
}
public void removeExemption(final Player player, final CheckType[] types){
for (final CheckType type : types){
exMan.removeExemption(player, type);
}
}
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
enabled = cfg.getBoolean(prefix + configPrefix + "enabled", true);
}
@Override
public boolean updateConfig(CompatConfig cfg, String prefix) {
CompatConfig defaults = CompatConfigFactory.getConfig(null);
defaults.set(prefix + configPrefix + "enabled", true);
return ConfigUtil.forceDefaults(defaults, cfg);
}
@Override
public boolean isEnabled() {
return enabled;
}
}

View File

@ -0,0 +1,82 @@
package me.asofold.bpl.cncp.hooks.GravityTubes;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.permissions.Permissible;
import com.benzoft.gravitytubes.GTPerm;
import com.benzoft.gravitytubes.GravityTube;
import com.benzoft.gravitytubes.files.ConfigFile;
import com.benzoft.gravitytubes.files.GravityTubesFile;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.IViolationInfo;
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.hooks.NCPHook;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.location.TrigUtil;
import me.asofold.bpl.cncp.hooks.GravityTubes.HookGravityTubes.HookFacade;
public class HookFacadeImpl implements HookFacade, NCPHook {
public HookFacadeImpl(){}
@Override
public String getHookName() {
return "GravityTubes(cncp)";
}
@Override
public String getHookVersion() {
return "1.1";
}
@Override
public final boolean onCheckFailure(final CheckType checkType, final Player player, final IViolationInfo info) {
//if (checkType == CheckType.MOVING_CREATIVEFLY && !ConfigFile.getInstance().isSneakToFall() )
if (player.getGameMode() == GameMode.SPECTATOR) return false;
if ((checkType == CheckType.MOVING_CREATIVEFLY || checkType == CheckType.MOVING_SURVIVALFLY) && GTPerm.USE.checkPermission((Permissible)player)) {
final GravityTube tube = GravityTubesFile.getInstance().getTubes().stream().filter(gravityTube -> isInTube(gravityTube, player, true, true)).findFirst().orElse(null);
if (tube != null) {
return true;
}
}
return false;
}
private boolean isInTube(GravityTube tube, Player p, boolean longerH, boolean extendxz) {
final int tubePower = tube.getPower();
int power = tubePower > 171 ? 4 : tubePower > 80 ? 3 : tubePower > 25 ? 2 : 1;
final Location pLoc = p.getLocation();
final Location tLoc = tube.getSourceLocation();
final boolean b1 = p.getWorld().equals(tLoc.getWorld()) && pLoc.getY() >= tLoc.getBlockY() && pLoc.getY() <= tLoc.getBlockY() + tube.getHeight() + (longerH ? power : 0);
if (!extendxz)
return b1 && pLoc.getBlockX() == tLoc.getBlockX() && pLoc.getBlockZ() == tLoc.getBlockZ();
return b1 && isTubeNearby(pLoc.getBlockX(), pLoc.getBlockZ(), tLoc.getBlockX(), tLoc.getBlockZ());
}
private boolean isTubeNearby(int x1, int z1, int x2, int z2) {
return TrigUtil.distance(x1,z1,x2,z2) < 1.5;
}
@Override
public void onMoveLowest(PlayerMoveEvent event) {
final Player p = event.getPlayer();
if (p.getGameMode() == GameMode.SPECTATOR) return;
final double hDist = TrigUtil.xzDistance(event.getFrom(), event.getTo());
final double vDist = event.getFrom().getY() - event.getTo().getY();
if (GTPerm.USE.checkPermission((Permissible)p)
&& vDist > 0 && hDist < 0.35
&& ConfigFile.getInstance().isDisableFallDamage() && p.isSneaking()) {
final GravityTube tube = GravityTubesFile.getInstance().getTubes().stream().filter(gravityTube -> isInTube(gravityTube, p, false, false)).findFirst().orElse(null);
final IPlayerData pData = DataManager.getPlayerData(p);
if (tube != null && pData != null) {
final MovingData mData = pData.getGenericInstance(MovingData.class);
mData.clearNoFallData();
}
}
}
}

View File

@ -0,0 +1,77 @@
package me.asofold.bpl.cncp.hooks.GravityTubes;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import fr.neatmonster.nocheatplus.hooks.NCPHook;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfigFactory;
import me.asofold.bpl.cncp.config.compatlayer.ConfigUtil;
import me.asofold.bpl.cncp.hooks.AbstractHook;
import me.asofold.bpl.cncp.hooks.generic.ConfigurableHook;
public class HookGravityTubes extends AbstractHook implements Listener, ConfigurableHook {
public static interface HookFacade{
public void onMoveLowest(PlayerMoveEvent event);
}
protected HookFacade ncpHook = null;
protected boolean enabled = true;
protected String configPrefix = "gravitytubes.";
public HookGravityTubes(){
assertPluginPresent("GravityTubes");
}
@Override
public String getHookName() {
return "GravityTubes(default)";
}
@Override
public String getHookVersion() {
return "1.0";
}
@Override
public Listener[] getListeners() {
return new Listener[]{
this
};
}
@Override
public NCPHook getNCPHook() {
if (ncpHook == null){
ncpHook = new HookFacadeImpl();
}
return (NCPHook) ncpHook;
}
@EventHandler(priority=EventPriority.LOWEST)
//@RegisterMethodWithOrder(tag = CompatNoCheatPlus.tagEarlyFeature, beforeTag = CompatNoCheatPlus.beforeTagEarlyFeature)
public final void onMoveLowest(final PlayerMoveEvent event){
ncpHook.onMoveLowest(event);
}
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
enabled = cfg.getBoolean(prefix + configPrefix + "enabled", true);
}
@Override
public boolean updateConfig(CompatConfig cfg, String prefix) {
CompatConfig defaults = CompatConfigFactory.getConfig(null);
defaults.set(prefix + configPrefix + "enabled", true);
return ConfigUtil.forceDefaults(defaults, cfg);
}
@Override
public boolean isEnabled() {
return enabled;
}
}

View File

@ -0,0 +1,64 @@
package me.asofold.bpl.cncp.hooks.generic;
import java.util.Arrays;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import fr.neatmonster.nocheatplus.checks.CheckType;
/**
* Wrap block break events to exempt players from checks by comparison of event class names.
* @author mc_dev
*
*/
public class HookBlockBreak extends ClassExemptionHook implements Listener {
public HookBlockBreak() {
super("block-break.");
defaultClasses.addAll(Arrays.asList(new String[]{
// MachinaCraft
"ArtificialBlockBreakEvent",
// mcMMO
"FakeBlockBreakEvent",
// MagicSpells
"MagicSpellsBlockBreakEvent"
}));
}
@Override
public String getHookName() {
return "BlockBreak(default)";
}
@Override
public String getHookVersion() {
return "1.1";
}
@Override
public Listener[] getListeners() {
return new Listener[]{this};
}
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
super.applyConfig(cfg, prefix);
if (classes.isEmpty()) enabled = false;
}
@EventHandler(priority = EventPriority.LOWEST)
final void onBlockBreakLowest(final BlockBreakEvent event){
checkExempt(event.getPlayer(), event.getClass(), CheckType.BLOCKBREAK);
}
@EventHandler(priority = EventPriority.MONITOR)
final void onBlockBreakMonitor(final BlockBreakEvent event){
checkUnexempt(event.getPlayer(), event.getClass(), CheckType.BLOCKBREAK);
}
}

View File

@ -0,0 +1,62 @@
package me.asofold.bpl.cncp.hooks.generic;
import java.util.Arrays;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import fr.neatmonster.nocheatplus.checks.CheckType;
/**
* Wrap block place events to exempt players from checks by comparison of event class names.
* @author mc_dev
*
*/
public class HookBlockPlace extends ClassExemptionHook implements Listener{
public HookBlockPlace() {
super("block-place.");
defaultClasses.addAll(Arrays.asList(new String[]{
// MachinaCraft
"ArtificialBlockPlaceEvent",
// MagicSpells
"MagicSpellsBlockPlaceEvent"
}));
}
@Override
public String getHookName() {
return "BlockPlace(default)";
}
@Override
public String getHookVersion() {
return "1.0";
}
@Override
public Listener[] getListeners() {
return new Listener[]{this};
}
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
super.applyConfig(cfg, prefix);
if (classes.isEmpty()) enabled = false;
}
@EventHandler(priority = EventPriority.LOWEST)
final void onBlockPlaceLowest(final BlockPlaceEvent event){
checkExempt(event.getPlayer(), event.getClass(), CheckType.BLOCKPLACE);
}
@EventHandler(priority = EventPriority.MONITOR)
final void onBlockPlaceMonitor(final BlockPlaceEvent event){
checkUnexempt(event.getPlayer(), event.getClass(), CheckType.BLOCKPLACE);
}
}

View File

@ -0,0 +1,66 @@
package me.asofold.bpl.cncp.hooks.generic;
import java.util.Arrays;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import fr.neatmonster.nocheatplus.checks.CheckType;
public class HookEntityDamageByEntity extends ClassExemptionHook implements
Listener {
public HookEntityDamageByEntity() {
super("entity-damage-by-entity.");
defaultClasses.addAll(Arrays.asList(new String[] {
// CrackShot
"WeaponDamageEntityEvent",
// MagicSpells
"MagicSpellsEntityDamageByEntityEvent" }));
}
@Override
public String getHookName() {
return "EntityDamageByEntity(default)";
}
@Override
public String getHookVersion() {
return "0.0";
}
@Override
public Listener[] getListeners() {
return new Listener[] { this };
}
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
super.applyConfig(cfg, prefix);
if (classes.isEmpty())
enabled = false;
}
@EventHandler(priority = EventPriority.LOWEST)
final void onDamageLowest(final EntityDamageByEntityEvent event) {
final Entity damager = event.getDamager();
if (damager instanceof Player) {
checkExempt((Player) damager, event.getClass(), CheckType.FIGHT);
}
}
@EventHandler(priority = EventPriority.MONITOR)
final void onDamageMonitor(final EntityDamageByEntityEvent event) {
final Entity damager = event.getDamager();
if (damager instanceof Player) {
checkUnexempt((Player) damager, event.getClass(), CheckType.FIGHT);
}
}
}

View File

@ -0,0 +1,171 @@
package me.asofold.bpl.cncp.hooks.generic;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfigFactory;
import me.asofold.bpl.cncp.config.compatlayer.ConfigUtil;
import me.asofold.bpl.cncp.hooks.AbstractHook;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockDamageEvent;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.utilities.TickTask;
public class HookInstaBreak extends AbstractHook implements ConfigurableHook, Listener {
public static interface InstaExemption{
public void addExemptNext(CheckType[] types);
public Set<CheckType> getExemptNext();
}
public static class StackEntry{
public final CheckType[] checkTypes;
public final int tick;
public final Player player;
public boolean used = false;
public StackEntry(final Player player , final CheckType[] checkTypes){
this.player = player;
this.checkTypes = checkTypes;
tick = TickTask.getTick();
}
public boolean isOutdated(final int tick){
return tick != this.tick;
}
}
protected static InstaExemption runtime = null;
public static void addExemptNext(final CheckType[] types){
runtime.addExemptNext(types);
}
protected final ExemptionManager exMan = new ExemptionManager();
protected boolean enabled = true;
protected final List<StackEntry> stack = new LinkedList<StackEntry>();
@Override
public String getHookName() {
return "InstaBreak(default)";
}
@Override
public String getHookVersion() {
return "1.0";
}
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
enabled = cfg.getBoolean(prefix + "insta-break.enabled", true);
}
@Override
public boolean updateConfig(CompatConfig cfg, String prefix) {
CompatConfig defaults = CompatConfigFactory.getConfig(null);
defaults.set(prefix + "insta-break.enabled", true);
return ConfigUtil.forceDefaults(defaults, cfg);
}
@Override
public boolean isEnabled() {
return enabled;
}
@Override
public CheckType[] getCheckTypes() {
return null;
}
@Override
public Listener[] getListeners() {
runtime = new InstaExemption() {
protected final Set<CheckType> types = new HashSet<CheckType>();
@Override
public final void addExemptNext(final CheckType[] types) {
for (int i = 0; i < types.length; i++){
this.types.add(types[i]);
}
}
@Override
public Set<CheckType> getExemptNext() {
return types;
}
};
return new Listener[]{this};
}
protected CheckType[] fetchTypes(){
final Set<CheckType> types = runtime.getExemptNext();
final CheckType[] a = new CheckType[types.size()];
if (!types.isEmpty()) types.toArray(a);
types.clear();
return a;
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = false)
public void onBlockDamage(final BlockDamageEvent event){
checkStack();
if (!event.isCancelled() && event.getInstaBreak()){
stack.add(new StackEntry(event.getPlayer(), fetchTypes()));
}
else{
runtime.getExemptNext().clear();
}
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = false)
public void onBlockBreakLowest(final BlockBreakEvent event){
checkStack();
if (!stack.isEmpty()){
final Player player = event.getPlayer();
final StackEntry entry = stack.get(stack.size() - 1);
if (player.equals(entry.player)) addExemption(entry);
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = false)
public void onBlockBreakMONITOR(final BlockBreakEvent event){
if (!stack.isEmpty()){
final Player player = event.getPlayer();
final StackEntry entry = stack.get(stack.size() - 1);
if (player.equals(entry.player)) removeExemption(stack.remove(stack.size() - 1));
}
}
public void addExemption(final StackEntry entry){
entry.used = true;
for (int i = 0; i < entry.checkTypes.length; i++){
exMan.addExemption(entry.player, entry.checkTypes[i]);
}
}
public void removeExemption(final StackEntry entry){
if (!entry.used) return;
for (int i = 0; i < entry.checkTypes.length; i++){
exMan.removeExemption(entry.player, entry.checkTypes[i]);
}
}
public void checkStack(){
if (stack.isEmpty()) return;
Iterator<StackEntry> it = stack.iterator();
final int tick = TickTask.getTick();
while (it.hasNext()){
final StackEntry entry = it.next();
if (entry.isOutdated(tick)) it.remove();
if (entry.used) removeExemption(entry);
}
}
}

View File

@ -0,0 +1,58 @@
package me.asofold.bpl.cncp.hooks.generic;
import fr.neatmonster.nocheatplus.checks.CheckType;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import java.util.Arrays;
/**
* Wrap player interact events to exempt players from checks by comparison of event class names.
* Uses mc_dev's format for exemption based upon class names.
*
*/
public class HookPlayerInteract extends ClassExemptionHook implements Listener{
public HookPlayerInteract() {
super("player-interact.");
defaultClasses.addAll(Arrays.asList(new String[]{
// MagicSpells
"MagicSpellsPlayerInteractEvent"
}));
}
@Override
public String getHookName() {
return "Interact(default)";
}
@Override
public String getHookVersion() {
return "1.0";
}
@Override
public Listener[] getListeners() {
return new Listener[]{this};
}
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
super.applyConfig(cfg, prefix);
if (classes.isEmpty()) enabled = false;
}
@EventHandler(priority = EventPriority.LOWEST)
final void onPlayerInteractLowest(final PlayerInteractEvent event){
checkExempt(event.getPlayer(), event.getClass(), CheckType.BLOCKINTERACT);
}
@EventHandler(priority = EventPriority.MONITOR)
final void onPlayerInteractMonitor(final PlayerInteractEvent event){
checkUnexempt(event.getPlayer(), event.getClass(), CheckType.BLOCKINTERACT);
}
}

View File

@ -0,0 +1,106 @@
package me.asofold.bpl.cncp.hooks.generic;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfigFactory;
import me.asofold.bpl.cncp.config.compatlayer.ConfigUtil;
import me.asofold.bpl.cncp.hooks.AbstractHook;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import fr.neatmonster.nocheatplus.checks.CheckType;
public class HookSetSpeed extends AbstractHook implements Listener, ConfigurableHook{
private static final float defaultFlySpeed = 0.1f;
private static final float defaultWalkSpeed = 0.2f;
protected float flySpeed = defaultFlySpeed;
protected float walkSpeed = defaultWalkSpeed;
protected boolean enabled = false;
// private String allowFlightPerm = "cncp.allow-flight";
public HookSetSpeed() throws SecurityException, NoSuchMethodException{
Player.class.getDeclaredMethod("setFlySpeed", float.class);
}
public void init(){
for (final Player player : Bukkit.getOnlinePlayers()){
setSpeed(player);
}
}
@Override
public String getHookName() {
return "SetSpeed(default)";
}
@Override
public String getHookVersion() {
return "2.2";
}
@Override
public CheckType[] getCheckTypes() {
return new CheckType[0];
}
@Override
public Listener[] getListeners() {
try{
// Initialize here, at the end of enable.
init();
}
catch (Throwable t){}
return new Listener[]{this} ;
}
public final void setSpeed(final Player player){
// if (allowFlightPerm.equals("") || player.hasPermission(allowFlightPerm)) player.setAllowFlight(true);
player.setWalkSpeed(walkSpeed);
player.setFlySpeed(flySpeed);
}
@EventHandler(priority=EventPriority.LOWEST)
public final void onPlayerJoin(final PlayerJoinEvent event){
setSpeed(event.getPlayer());
}
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
enabled = cfg.getBoolean(prefix + "set-speed.enabled", false);
flySpeed = cfg.getDouble(prefix + "set-speed.fly-speed", (double) defaultFlySpeed).floatValue();
walkSpeed = cfg.getDouble(prefix + "set-speed.walk-speed", (double) defaultWalkSpeed).floatValue();
// allowFlightPerm = cfg.getString(prefix + "set-speed.allow-flight-permission", ref.allowFlightPerm);
}
@Override
public boolean updateConfig(CompatConfig cfg, String prefix) {
CompatConfig defaults = CompatConfigFactory.getConfig(null);
defaults.set(prefix + "set-speed.enabled", false);
defaults.set(prefix + "set-speed.fly-speed", defaultFlySpeed);
defaults.set(prefix + "set-speed.walk-speed", defaultWalkSpeed);
// cfg.set(prefix + "set-speed.allow-flight-permission", ref.allowFlightPerm);
return ConfigUtil.forceDefaults(defaults, cfg);
}
@Override
public boolean isEnabled() {
return enabled;
}
// public String getAllowFlightPerm() {
// return allowFlightPerm;
// }
// public void setAllowFlightPerm(String allowFlightPerm) {
// this.allowFlightPerm = allowFlightPerm;
// }
}

View File

@ -89,12 +89,12 @@ public class HookMagicSpells extends AbstractConfigurableHook implements Listene
catch(Throwable t){
}
if (type == null){
Bukkit.getLogger().warning("[cncp] HookMagicSpells: Bad check type at " + fullKey + ": " + input);
Bukkit.getLogger().warning("[CompatNoCheatPlus] HookMagicSpells: Bad check type at " + fullKey + ": " + input);
}
else checkTypes.add(type);
}
if (checkTypes.isEmpty()){
Bukkit.getLogger().warning("[cncp] HookMagicSpells: No CheckType entries at: " + fullKey);
Bukkit.getLogger().warning("[CompatNoCheatPlus] HookMagicSpells: No CheckType entries at: " + fullKey);
}
else{
CheckType[] a = new CheckType[checkTypes.size()];

View File

@ -12,6 +12,8 @@ import org.bukkit.inventory.ItemStack;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.IViolationInfo;
import fr.neatmonster.nocheatplus.compat.Bridge1_9;
import fr.neatmonster.nocheatplus.compat.Folia;
import fr.neatmonster.nocheatplus.hooks.NCPHook;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
@ -160,14 +162,14 @@ public class HookFacadeImpl implements HookFacade, NCPHook {
public final void blockDamageLowest(final Player player) {
// System.out.println("block damage lowest");
// setPlayer(player, cancelChecksBlockDamage);
if (getToolProps(player.getItemInHand()).toolType == ToolType.AXE) addExemption(player, exemptBreakMany);
if (getToolProps(Bridge1_9.getItemInMainHand(player)).toolType == ToolType.AXE) addExemption(player, exemptBreakMany);
else addExemption(player, exemptBreakNormal);
}
@Override
public final boolean blockBreakLowest(final Player player) {
// System.out.println("block break lowest");
final boolean isAxe = getToolProps(player.getItemInHand()).toolType == ToolType.AXE;
final boolean isAxe = getToolProps(Bridge1_9.getItemInMainHand(player)).toolType == ToolType.AXE;
if (breakCancel > 0){
breakCancel ++;
return true;
@ -200,12 +202,7 @@ public class HookFacadeImpl implements HookFacade, NCPHook {
}
else if (!isAxe){
setPlayer(player, cancelChecksBlockBreak);
Bukkit.getScheduler().scheduleSyncDelayedTask(CompatNoCheatPlus.getInstance(), new Runnable() {
@Override
public void run() {
DataManager.removeData(player.getName(), CheckType.BLOCKBREAK_FASTBREAK);
}
});
Folia.runSyncTask(CompatNoCheatPlus.getInstance(), (arg) -> DataManager.removeData(player.getName(), CheckType.BLOCKBREAK_FASTBREAK));
}
return false;
}

View File

@ -0,0 +1,178 @@
package me.asofold.bpl.cncp.hooks.mcmmo;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfig;
import me.asofold.bpl.cncp.config.compatlayer.CompatConfigFactory;
import me.asofold.bpl.cncp.config.compatlayer.ConfigUtil;
import me.asofold.bpl.cncp.hooks.AbstractHook;
import me.asofold.bpl.cncp.hooks.generic.ConfigurableHook;
import me.asofold.bpl.cncp.utils.PluginGetter;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import com.gmail.nossr50.mcMMO;
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.CheckType;
import fr.neatmonster.nocheatplus.hooks.NCPHook;
public final class HookmcMMO extends AbstractHook implements Listener, ConfigurableHook {
/**
* To let the listener access this.
* @author mc_dev
*
*/
public static interface HookFacade{
public void damageLowest(Player player);
public void damageMonitor(Player player);
public void blockDamageLowest(Player player);
public void blockDamageMonitor(Player player);
/**
* If to cancel the event.
* @param player
* @return
*/
public boolean blockBreakLowest(Player player);
public void blockBreakMontitor(Player player);
}
protected HookFacade ncpHook = null;
protected boolean enabled = true;
protected String configPrefix = "mcmmo.";
protected boolean useInstaBreakHook = true;
public HookmcMMO(){
assertPluginPresent("mcMMO");
}
protected final PluginGetter<mcMMO> fetch = new PluginGetter<mcMMO>("mcMMO");
protected int blocksPerSecond = 30;
@Override
public String getHookName() {
return "mcMMO(default)";
}
@Override
public String getHookVersion() {
return "2.1";
}
@Override
public CheckType[] getCheckTypes() {
return new CheckType[]{
CheckType.BLOCKBREAK_FASTBREAK, CheckType.BLOCKBREAK_NOSWING, // old ones
// CheckType.BLOCKBREAK_DIRECTION, CheckType.BLOCKBREAK_FREQUENCY,
// CheckType.BLOCKBREAK_WRONGBLOCK, CheckType.BLOCKBREAK_REACH,
//
// CheckType.FIGHT_ANGLE, CheckType.FIGHT_SPEED, // old ones
//
// CheckType.FIGHT_DIRECTION, CheckType.FIGHT_NOSWING,
// CheckType.FIGHT_REACH,
};
}
@Override
public Listener[] getListeners() {
fetch.fetchPlugin();
return new Listener[]{this, fetch};
}
@Override
public NCPHook getNCPHook() {
if (ncpHook == null){
ncpHook = new HookFacadeImpl(useInstaBreakHook, blocksPerSecond);
}
return (NCPHook) ncpHook;
}
///////////////////////////
// Damage (fight)
//////////////////////////
@EventHandler(priority=EventPriority.LOWEST)
final void onDamageLowest(final FakeEntityDamageByEntityEvent event){
final Entity entity = event.getDamager();
if (entity instanceof Player)
ncpHook.damageLowest((Player) entity);
}
@EventHandler(priority=EventPriority.MONITOR)
final void onDamageMonitor(final FakeEntityDamageByEntityEvent event){
final Entity entity = event.getDamager();
if (entity instanceof Player)
ncpHook.damageMonitor((Player) entity);
}
///////////////////////////
// Block damage
//////////////////////////
@EventHandler(priority=EventPriority.LOWEST)
final void onBlockDamageLowest(final FakeBlockDamageEvent event){
ncpHook.blockDamageLowest(event.getPlayer());
}
@EventHandler(priority=EventPriority.LOWEST)
final void onBlockDamageMonitor(final FakeBlockDamageEvent event){
ncpHook.blockDamageMonitor(event.getPlayer());
}
///////////////////////////
// Block break
//////////////////////////
@EventHandler(priority=EventPriority.LOWEST)
final void onBlockBreakLowest(final FakeBlockBreakEvent event){
if (ncpHook.blockBreakLowest(event.getPlayer())){
event.setCancelled(true);
// System.out.println("Cancelled for frequency.");
}
}
@EventHandler(priority=EventPriority.MONITOR)
final void onBlockBreakLMonitor(final FakeBlockBreakEvent event){
ncpHook.blockBreakMontitor(event.getPlayer());
}
/////////////////////////////////
// Config
/////////////////////////////////
@Override
public void applyConfig(CompatConfig cfg, String prefix) {
enabled = cfg.getBoolean(prefix + configPrefix + "enabled", true);
useInstaBreakHook = cfg.getBoolean(prefix + configPrefix + "use-insta-break-hook", true);
blocksPerSecond = cfg.getInt(prefix + configPrefix + "clickspersecond", 20);
}
@Override
public boolean updateConfig(CompatConfig cfg, String prefix) {
CompatConfig defaults = CompatConfigFactory.getConfig(null);
defaults.set(prefix + configPrefix + "enabled", true);
defaults.set(prefix + configPrefix + "use-insta-break-hook", true);
defaults.set(prefix + configPrefix + "clickspersecond", 20);
return ConfigUtil.forceDefaults(defaults, cfg);
}
@Override
public boolean isEnabled() {
return enabled;
}
}