mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2025-03-12 22:49:31 +01:00
Rough sketch of workaround confinement and statistics support.
Untested, unused. Intentions are: * Be able to count any use of workarounds. * Confine workarounds to side conditions, such as 'use once until conditions are reset' and/or 'only use once conditions are set'. * Have per-player objects and (attached) global counters. * (Might think of: disable workarounds by configuration.)
This commit is contained in:
parent
027079320e
commit
567ef1b971
@ -0,0 +1,62 @@
|
||||
package fr.neatmonster.nocheatplus.workaround;
|
||||
|
||||
/**
|
||||
* Implementing the minimum features for counting use, plus the ability to trigger a parent
|
||||
* count.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractWorkaround implements Workaround {
|
||||
|
||||
private final String id;
|
||||
private final Workaround parent;
|
||||
private int useCount = 0;
|
||||
|
||||
public AbstractWorkaround(String id) {
|
||||
this(id, null); // No parent.
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param id
|
||||
* @param parent
|
||||
* For (global) count: parent.use() is called from within
|
||||
* this.use(), but the result is not evaluate.
|
||||
*/
|
||||
public AbstractWorkaround(String id, Workaround parent) {
|
||||
this.id = id;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public Workaround getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUseCount() {
|
||||
return useCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean use() {
|
||||
if (canUse()) {
|
||||
useCount ++;
|
||||
if (parent != null) {
|
||||
// TODO: Might consider a hierarchy (parent could overrule the result to false).
|
||||
parent.use();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// DenyUseCound is handled in sub-classes, if needed.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
package fr.neatmonster.nocheatplus.workaround;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Simple registry for workarounds. No thread-safety built in.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public class SimpleWorkaroundRegistry implements WorkaroundRegistry {
|
||||
|
||||
/** Global counter by id. */
|
||||
private final Map<String, WorkaroundCounter> counters = new HashMap<String, WorkaroundCounter>();
|
||||
|
||||
/** Workaround blue print by id. */
|
||||
private final Map<String, Workaround> bluePrints = new HashMap<String, Workaround>();
|
||||
|
||||
/** Map group id to array of workaround ids. */
|
||||
private final Map<String, String[]> groups = new HashMap<String, String[]>();
|
||||
|
||||
/** Map WorkaroundSet id to the contained blueprint ids. */
|
||||
private final Map<String, String[]> workaroundSets = new HashMap<String, String[]>();
|
||||
|
||||
/** Map WorkaroundSet id to the contained group ids. Might not contain entries for all ids. */
|
||||
private final Map<String, String[]> workaroundSetGroups = new HashMap<String, String[]>();
|
||||
|
||||
@Override
|
||||
public void setWorkaroundBluePrint(final Workaround... bluePrints) {
|
||||
for (int i = 0; i < bluePrints.length; i++) {
|
||||
final Workaround workaround = bluePrints[i];
|
||||
this.bluePrints.put(workaround.getId(), workaround.getNewInstance());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroup(final String groupId, final Collection<String> workaroundIds) {
|
||||
groups.put(groupId, workaroundIds.toArray(new String[workaroundIds.size()]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWorkaroundSet(final String workaroundSetId, final Collection<Workaround> bluePrints, final String... groupIds) {
|
||||
final String[] ids = new String[bluePrints.size()];
|
||||
int i = 0;
|
||||
for (final Workaround bluePrint : bluePrints) {
|
||||
final String id = bluePrint.getId();
|
||||
if (!this.bluePrints.containsKey(id)) {
|
||||
// Lazily register.
|
||||
setWorkaroundBluePrint(bluePrint);
|
||||
}
|
||||
ids[i] = id;
|
||||
i ++;
|
||||
}
|
||||
this.workaroundSets.put(workaroundSetId, ids);
|
||||
if (groupIds != null && groupIds.length > 0) {
|
||||
for (i = 0; i < groupIds.length; i++) {
|
||||
if (!this.groups.containsKey(groupIds[i])) {
|
||||
throw new IllegalArgumentException("Group not registered: " + groupIds[i]);
|
||||
}
|
||||
}
|
||||
this.workaroundSetGroups.put(workaroundSetId, groupIds);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWorkaroundSetByIds(final String workaroundSetId, final Collection<String> bluePrintIds, final String... groupIds) {
|
||||
final List<Workaround> bluePrints = new ArrayList<Workaround>(bluePrintIds.size());
|
||||
for (final String id : bluePrintIds) {
|
||||
final Workaround bluePrint = this.bluePrints.get(id);
|
||||
if (bluePrint == null) {
|
||||
throw new IllegalArgumentException("the blueprint is not registered: " + id);
|
||||
}
|
||||
bluePrints.add(bluePrint);
|
||||
}
|
||||
setWorkaroundSet(workaroundSetId, bluePrints, groupIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkaroundSet getWorkaroundSet(final String workaroundSetId) {
|
||||
final String[] workaroundIds = workaroundSets.get(workaroundSetId);
|
||||
if (workaroundIds == null) {
|
||||
throw new IllegalArgumentException("WorkaroundSet not registered: " + workaroundSetId);
|
||||
}
|
||||
final Workaround[] bluePrints = new Workaround[workaroundIds.length];
|
||||
for (int i = 0; i < workaroundIds.length; i++) {
|
||||
bluePrints[i] = this.bluePrints.get(workaroundIds[i]).getNewInstance();
|
||||
}
|
||||
final Map<String, String[]> groups;
|
||||
final String[] groupIds = this.workaroundSetGroups.get(workaroundSetId);
|
||||
if (groupIds == null) {
|
||||
groups = null;
|
||||
}
|
||||
else {
|
||||
groups = new HashMap<String, String[]>();
|
||||
for (int i = 0; i < groupIds.length; i++) {
|
||||
final String groupId = groupIds[i];
|
||||
groups.put(groupId, this.groups.get(groupId));
|
||||
}
|
||||
}
|
||||
return new WorkaroundSet(bluePrints, groups);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkaroundCounter getGlobalCounter(final String id) {
|
||||
return counters.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkaroundCounter createGlobalCounter(final String id) {
|
||||
WorkaroundCounter counter = counters.get(id);
|
||||
if (counter == null) {
|
||||
counter = new WorkaroundCounter(id);
|
||||
counters.put(id, counter);
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <C extends Workaround> C getWorkaround(final String id, final Class<C> workaroundClass) {
|
||||
final Workaround workaround = getWorkaround(id);
|
||||
if (workaroundClass.isAssignableFrom(workaround.getClass())) {
|
||||
return (C) workaround;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unsupported class for id '" + id + "': " + workaroundClass.getName() + " (actual class is " + workaround.getClass().getName() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Workaround getWorkaround(final String id) {
|
||||
final Workaround bluePrint = bluePrints.get(id);
|
||||
if (bluePrint == null) {
|
||||
throw new IllegalArgumentException("Id not registered as blueprint: " + id);
|
||||
}
|
||||
return bluePrint.getNewInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Integer> getGlobalUseCount() {
|
||||
final Map<String, Integer> currentCounts = new LinkedHashMap<String, Integer>(counters.size());
|
||||
for (final WorkaroundCounter counter : counters.values()) {
|
||||
currentCounts.put(counter.getId(), counter.getUseCount());
|
||||
}
|
||||
return currentCounts;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package fr.neatmonster.nocheatplus.workaround;
|
||||
|
||||
/**
|
||||
* Provide a means of controlling when workarounds should be able to apply,
|
||||
* enabling preconditions, mid-to-long-term side-conditions, as well as
|
||||
* statistics for how often a workaround has been used.
|
||||
* <hr>
|
||||
* The method use() must be called after all other preconditions have been met
|
||||
* for that (stage of) workaround, so that success means that the (stage of)
|
||||
* workaround does apply. The method canUse can be used to test if the
|
||||
* workaround would apply, aimed at cases where that is better performance-wise.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public interface Workaround {
|
||||
|
||||
// TODO: getDiscardCount() ?
|
||||
// TODO: Add setEnabled() ? Allow to configure workarounds.
|
||||
|
||||
public String getId();
|
||||
|
||||
/** The all-time use count. */
|
||||
public int getUseCount();
|
||||
|
||||
/**
|
||||
* Attempt to use the workaround, considering all preconditions and
|
||||
* side-conditions set. This will increase the use count in case of
|
||||
* returning true, it might also alter/use other counters based on the value
|
||||
* to be returned.
|
||||
*
|
||||
* @return If actually can be used.
|
||||
*/
|
||||
public boolean use();
|
||||
|
||||
/**
|
||||
* Test if this (stage of) workaround would apply, excluding checking for
|
||||
* parent state. This must not have any side effect nor change any data.
|
||||
* This should also not call parent.canUse, as that would lead to quadratic
|
||||
* time checking with a deeper hierarchy (likely it's just 1 deep).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean canUse();
|
||||
|
||||
/**
|
||||
* Generic reset to the initial conditions. This does not reset the use
|
||||
* count, other effects depend on the implementation.
|
||||
*/
|
||||
public void resetConditions();
|
||||
|
||||
/**
|
||||
* Serving as factory, retrieve a new instance of the same kind, in the
|
||||
* default state (not clone).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Workaround getNewInstance();
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package fr.neatmonster.nocheatplus.workaround;
|
||||
|
||||
/**
|
||||
* Count down to 0, use is only possible if the currentCounter is greater than
|
||||
* 0. An initialCounter of 0 together with setting the currentCount manually,
|
||||
* allows to activate a workaround on base of a precondition.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public class WorkaroundCountDown extends AbstractWorkaround {
|
||||
|
||||
private final int initialCount;
|
||||
private int currentCount;
|
||||
|
||||
public WorkaroundCountDown(String id, int initialCount, Workaround parent) {
|
||||
super(id, parent);
|
||||
this.initialCount = initialCount;
|
||||
this.currentCount = initialCount;
|
||||
}
|
||||
|
||||
public void setCurrentCount(int currentCount) {
|
||||
this.currentCount = currentCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean use() {
|
||||
// Adjust currentCount based on super.use().
|
||||
if (super.use()) {
|
||||
currentCount --;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
return currentCount > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetConditions() {
|
||||
currentCount = initialCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkaroundCountDown getNewInstance() {
|
||||
return new WorkaroundCountDown(getId(), initialCount, getParent());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package fr.neatmonster.nocheatplus.workaround;
|
||||
|
||||
/**
|
||||
* Simply count times used.
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public class WorkaroundCounter extends AbstractWorkaround {
|
||||
|
||||
public WorkaroundCounter(String id, Workaround parent) {
|
||||
super(id, parent);
|
||||
}
|
||||
|
||||
public WorkaroundCounter(String id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
// Just counting.
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetConditions() {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkaroundCounter getNewInstance() {
|
||||
return new WorkaroundCounter(getId());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,225 @@
|
||||
package fr.neatmonster.nocheatplus.workaround;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* An access point for fetching global WorkaroundCounter instances and a factory
|
||||
* for fetching new sets of per-player workarounds.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public interface WorkaroundRegistry {
|
||||
|
||||
/**
|
||||
* Convenience to retrieve any type of per-player Workaround by id, for the
|
||||
* case one doesn't want to store the registry and/or individual Workaround
|
||||
* implementations as members. Groups allow resetting certain types of
|
||||
* workarounds in bunches.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public static class WorkaroundSet {
|
||||
|
||||
// TODO: getUseCount()
|
||||
// TODO: A list for ids of just used workarounds (reset externally. Add use(id) vs alter Workaround)?
|
||||
// TODO: Better optimized constructor.
|
||||
|
||||
/** Map workaround id to workaround. */
|
||||
private final Map<String, Workaround> workaroundsById = new LinkedHashMap<String, Workaround>();
|
||||
|
||||
/** Only the workarounds that might need resetting. */
|
||||
private final Workaround[] mightNeedReset;
|
||||
|
||||
/** Map groupId to workarounds. */
|
||||
private final Map<String, Workaround[]> groups;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param bluePrints
|
||||
* @param groups
|
||||
* Map groupId to workaroundIds, groups may be null if none
|
||||
* are set. All referenced workaround ids must be registered,
|
||||
* workarounds can be in multiple groups.
|
||||
*/
|
||||
public WorkaroundSet(final Workaround[] bluePrints, final Map<String, String[]> groups) {
|
||||
final Class<?> excludeFromReset = WorkaroundCounter.class;
|
||||
final List<Workaround> mightNeedReset = new ArrayList<Workaround>(bluePrints.length);
|
||||
for (int i = 0; i < bluePrints.length; i++) {
|
||||
final Workaround workaround = bluePrints[i].getNewInstance();
|
||||
workaroundsById.put(workaround.getId(), workaround);
|
||||
if (workaround.getClass() != excludeFromReset) {
|
||||
mightNeedReset.add(workaround);
|
||||
}
|
||||
}
|
||||
this.mightNeedReset = mightNeedReset.toArray(new Workaround[mightNeedReset.size()]);
|
||||
// Prepare fast to reset lists, if groups are given.
|
||||
if (groups != null) {
|
||||
this.groups = new HashMap<String, Workaround[]>();
|
||||
for (final Entry<String, String[]> entry : groups.entrySet()) {
|
||||
final String[] workaroundIds = entry.getValue();
|
||||
final Workaround[] group = new Workaround[workaroundIds.length];
|
||||
for (int i = 0; i < workaroundIds.length; i++) {
|
||||
group[i] = getWorkaround(workaroundIds[i]);
|
||||
}
|
||||
this.groups.put(entry.getKey(), group);
|
||||
}
|
||||
} else {
|
||||
this.groups = null;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <C extends Workaround> C getWorkaround(final String id, final Class<C> workaroundClass) {
|
||||
final Workaround present = getWorkaround(id);
|
||||
if (!workaroundClass.isAssignableFrom(present.getClass())) {
|
||||
throw new IllegalArgumentException("Wrong type of registered workaround requested: " + workaroundClass.getName() + " instead of " + present.getClass().getName());
|
||||
} else {
|
||||
return (C) present;
|
||||
}
|
||||
}
|
||||
|
||||
public Workaround getWorkaround(final String id) {
|
||||
final Workaround present = workaroundsById.get(id);
|
||||
if (present == null) {
|
||||
throw new IllegalArgumentException("Workaround id not registered: " + id);
|
||||
}
|
||||
return present;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call resetConditions for all stored workarounds, excluding
|
||||
* WorkaroundCounter instances (sub classes get reset too).
|
||||
*/
|
||||
public void resetConditions() {
|
||||
for (int i = 0; i < mightNeedReset.length; i++) {
|
||||
mightNeedReset[i].resetConditions();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call resetConditions for all workarounds that are within the group
|
||||
* with the given groupId.
|
||||
*
|
||||
* @param groupId
|
||||
*/
|
||||
public void resetConditions(final String groupId) {
|
||||
final Workaround[] workarounds = groups.get(groupId);
|
||||
if (workarounds == null) {
|
||||
throw new IllegalArgumentException("Group not registered: " + groupId);
|
||||
}
|
||||
for (int i = 0; i < workarounds.length; i++) {
|
||||
workarounds[i].resetConditions();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: Might make getWorkaround non public, to favor use of WorkaroundSet.
|
||||
|
||||
/**
|
||||
* Registers workaround.getNewInstance() for the set id. Set parent to
|
||||
* createGlobalCounter(id), if a global counter is desired.
|
||||
*
|
||||
* @param bluePrints
|
||||
*/
|
||||
public void setWorkaroundBluePrint(Workaround...bluePrints);
|
||||
|
||||
/**
|
||||
* Specify what workaround ids belong to a certain group. Workarounds can be
|
||||
* in multiple groups.
|
||||
*
|
||||
* @param groupId
|
||||
* @param workaroundIds
|
||||
*/
|
||||
public void setGroup(String groupId, Collection<String> workaroundIds);
|
||||
|
||||
/**
|
||||
* Define which workarounds and which groups belong to the WorkaroundSet of
|
||||
* the given workaroundSetId.
|
||||
*
|
||||
* @param workaroundSetId
|
||||
* @param bluePrints
|
||||
* Lazily registers, if no blueprint is present. Already
|
||||
* registered blueprints are kept.
|
||||
* @param groupIds
|
||||
* Must already be registered.
|
||||
*/
|
||||
public void setWorkaroundSet(String workaroundSetId, Collection<Workaround> bluePrints, String... groupIds);
|
||||
|
||||
/**
|
||||
* Define which workarounds and which groups belong to the WorkaroundSet of
|
||||
* the given workaroundSetId.
|
||||
*
|
||||
* @param workaroundSetId
|
||||
* @param bluePrintIds
|
||||
* @param groupIds
|
||||
*/
|
||||
public void setWorkaroundSetByIds(String workaroundSetId, Collection<String> bluePrintIds, String... groupIds);
|
||||
|
||||
/**
|
||||
* Retrieve a pre-set WorkaroundSet instance with new Workaround instances
|
||||
* generated from the blueprints.
|
||||
*
|
||||
* @param workaroundSetId
|
||||
* @return
|
||||
*/
|
||||
public WorkaroundSet getWorkaroundSet(String workaroundSetId);
|
||||
|
||||
/**
|
||||
* Get a registered global WorkaroundCounter, if registered.
|
||||
*
|
||||
* @param id
|
||||
* @return The registered WorkaroundCounter instance, or null if none is
|
||||
* registered for the given id.
|
||||
*/
|
||||
public WorkaroundCounter getGlobalCounter(String id);
|
||||
|
||||
/**
|
||||
* Get a registered global WorkaroundCounter, create if not present.
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
public WorkaroundCounter createGlobalCounter(String id);
|
||||
|
||||
/**
|
||||
* Retrieve a new instance, ready for use, attached to a global counter of
|
||||
* the same id.
|
||||
*
|
||||
* @param id
|
||||
* @param workaroundClass
|
||||
* Specific type to use. The registry may have a blueprint set
|
||||
* and just clone that.
|
||||
* @return
|
||||
* @throws IllegalArgumentException
|
||||
* If either of id or workaroundClass is not possible to use.
|
||||
*/
|
||||
public <C extends Workaround> C getWorkaround(String id, Class<C> workaroundClass);
|
||||
|
||||
/**
|
||||
* Retrieve a new instance, ready for use, attached to a global counter of
|
||||
* the same id.
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
* @throws IllegalArgumentException
|
||||
* If either of id or workaroundClass is not possible to use.
|
||||
*/
|
||||
public Workaround getWorkaround(String id);
|
||||
|
||||
/**
|
||||
* Get all global count values by id.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Map<String, Integer> getGlobalUseCount();
|
||||
|
||||
}
|
@ -696,6 +696,7 @@ public class SurvivalFly extends Check {
|
||||
// Hack for allow sprint-jumping with slowness.
|
||||
if (sprinting && hAllowedDistance < 0.29 && cc.sfSlownessSprintHack && player.hasPotionEffect(PotionEffectType.SLOW)) {
|
||||
// TODO: Should restrict further by yDistance, ground and other (jumping only).
|
||||
// TODO: Restrict to not in water (depth strider)?
|
||||
hAllowedDistance = slownessSprintHack(player, hAllowedDistance);
|
||||
}
|
||||
}
|
||||
|
@ -658,6 +658,8 @@ public abstract class ConfPaths {
|
||||
public static final String COMPATIBILITY_EXEMPTIONS_REMOVE = COMPATIBILITY_EXEMPTIONS + "remove.";
|
||||
public static final String COMPATIBILITY_EXEMPTIONS_REMOVE_JOIN = COMPATIBILITY_EXEMPTIONS_REMOVE + "join";
|
||||
public static final String COMPATIBILITY_EXEMPTIONS_REMOVE_LEAVE = COMPATIBILITY_EXEMPTIONS_REMOVE + "leave";
|
||||
// TODO: remove: tick, metadata.
|
||||
// TODO: npcs: active, checks (default: fight, moving, all the noswings, wrongblock etc.)
|
||||
|
||||
public static final String COMPATIBILITY_SERVER = COMPATIBILITY + "server.";
|
||||
public static final String COMPATIBILITY_SERVER_CBDEDICATED = COMPATIBILITY_SERVER + "cbdedicated.";
|
||||
|
@ -7,6 +7,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.entity.NPC;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
@ -119,9 +120,21 @@ public class NCPExemptionManager {
|
||||
*/
|
||||
public static final boolean isExempted(final Player player, final CheckType checkType) {
|
||||
// TODO: Settings: If to check meta data at all.
|
||||
// TODO: Settings: check types to exempt npcs from (and if to use) -> implement setSettings
|
||||
return isExempted(player.getUniqueId(), checkType) || player.hasMetadata("nocheat.exempt");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a player is an npc, using current settings.
|
||||
*
|
||||
* @param player
|
||||
* @return
|
||||
*/
|
||||
public static final boolean isNpc(final Player player) {
|
||||
// TODO: Configurability: Which metadata key(s + if).
|
||||
return (player instanceof NPC) || player.hasMetadata("npc");
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo exempting an entity from all checks. Includes players, note that
|
||||
* exemption by meta data is not removed here.
|
||||
|
Loading…
Reference in New Issue
Block a user