/* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package fr.neatmonster.nocheatplus.checks; import java.util.HashMap; import java.util.Map; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import fr.neatmonster.nocheatplus.NCPAPIProvider; import fr.neatmonster.nocheatplus.actions.ActionList; import fr.neatmonster.nocheatplus.actions.types.penalty.IPenaltyList; import fr.neatmonster.nocheatplus.compat.MCAccess; import fr.neatmonster.nocheatplus.components.debug.IDebugPlayer; import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle; import fr.neatmonster.nocheatplus.hooks.NCPHookManager; import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.ExecutionHistory; import fr.neatmonster.nocheatplus.players.IPlayerData; import fr.neatmonster.nocheatplus.utilities.CheckUtils; import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.worlds.IWorldData; /** * The parent class of all checks. Don't let this implement Listener without * knowing that this might be registered as component with NCP before the * check-listeners. *
* Note on enabling and bypassing:
*
  • The full Check.isEnabled test will check the config flag * (config.isEnabled) and test Check.hasBypass (permissions, exemption).
  • *
  • Currently the code for isEnabled and hasBypasss is in * fr.neatmonster.nocheatplus.utilities.CheckUtils .
  • *
  • Currently the hasBypass check will test for a permission if in the main * thread, or test for a cached permission if off the main thread, then check * for exemption with fr.neatmonster.nocheatplus.hooks.NCPExemptionManager, for * the case that no bypass permission is present.
  • *
  • For checks run off the primary thread, permissions are cached. Updates * must be requested with the TickTask explicitly, e.g. in the listener. This * depends on the definition of which checks might run asynchronously, as given * in fr.neatmonster.nocheatplus.hooks.APIUtils and the default permissions * defined in ICheckConfig implementations.
  • *
  • At present exemption checking is only thread-safe for the checks that are * set to run off main thread (APIUtils).
  • *
    * Note on performance: *
  • You might check the configuration flag directly with a given * configuration, which is equivalent to but supposedly faster than calling * CheckType.isEnabled(player) or CheckConfig.isEnabled(player). Then call * hasBypass extra to that.
  • *
  • For very simple checks, you might skip checking hasBypass for the normal * case, and check it lazily only in case of a violation.
  • *
  • The method signatures that take ICheckData and ICheckConfig as extra * arguments will perform better, they also allow to pass null for config and * data (also see fr.neatmonster.nocheatplus.utilities.CheckUtils).
  • *
  • In case simplicity of code is demanded, just check isEnabled(player) or * for better performance isEnabled(player, data, config), before running the * actual check.
  • * */ // TODO: javadocs redo (above) public abstract class Check implements IDebugPlayer { // TODO: Do these get cleaned up ? /** The execution histories of each check. */ protected static Map histories = new HashMap(); /** * Gets the player's history. * * @param player * the player * @return the history */ protected static ExecutionHistory getHistory(final Player player) { if (!histories.containsKey(player.getName())) { histories.put(player.getName(), new ExecutionHistory()); } return histories.get(player.getName()); } /** The type. */ protected final CheckType type; protected final IGenericInstanceHandle mcAccess; /** * Instantiates a new check. * * @param type * the type */ @SuppressWarnings("deprecation") public Check(final CheckType type) { this.type = type; mcAccess = NCPAPIProvider.getNoCheatPlusAPI().getGenericInstanceHandle(MCAccess.class); ViolationHistory.checkTypeMap.put(getClass().getName(), type); DataManager.registerExecutionHistory(type, histories); } /** * Execute actions, thread-safe.
    * * @param player * The player who failed a check. * @param vL * The total check-specific violation level. * @param addedVL * The violation level, that has been added with this violation. * @param actions * The ActionList to use for this violation. * @param penaltyList * IPenaltyList instance to fill in penalties for specific input * other than Player. * @return The ViolationData instance that is created for execution of * actions. */ public ViolationData executeActions(final Player player, final double vL, final double addedVL, final ActionList actions, final IPenaltyList penaltyList) { return executeActions(new ViolationData(this, player, vL, addedVL, actions, penaltyList)); } /** * Execute actions, thread-safe.
    * * @param player * The player who failed a check. * @param vL * The total check-specific violation level. * @param addedVL * The violation level, that has been added with this violation. * @param actions * The ActionList to use for this violation. * @return The ViolationData instance that is created for execution of * actions. */ public ViolationData executeActions(final Player player, final double vL, final double addedVL, final ActionList actions) { return executeActions(new ViolationData(this, player, vL, addedVL, actions)); } /** * Execute actions, thread safe. * * @param violationData * the violation data * @return The ViolationData instanced passed to this method. */ public ViolationData executeActions(final ViolationData violationData) { // Dispatch the VL processing to the hook manager (now thread safe). if (NCPHookManager.shouldCancelVLProcessing(violationData)) { // One of the hooks has decided to cancel the VL processing, return false. violationData.preventCancel(); } else if (Bukkit.isPrimaryThread()) { violationData.executeActions(); } else { // Always schedule to add to ViolationHistory. // TODO: Might clear input-specific effects (stored ones will be handled extra to those). TickTask.requestActionsExecution(violationData); } // (Permission checks are moved to cached permissions, lazily updated.) return violationData; } /** * Gets the type of the check. * * @return the type */ public CheckType getType() { return type; } /** * Full activation check (configuration, exemption, permission). * * @param player * @param data * @param worldData * @return */ public boolean isEnabled(final Player player, final IPlayerData pData, final IWorldData worldData) { return pData.isCheckActive(type, player, worldData); } /** * Full activation check (configuration, exemption, permission). * * @param player * @param data * @return */ public boolean isEnabled(final Player player, final IPlayerData pData) { return pData.isCheckActive(type, player); } /** * Full activation check (configuration, exemption, permission). * * @param player * the player * @return true, if the check is enabled */ public boolean isEnabled(final Player player) { return isEnabled(player, DataManager.getPlayerData(player)); } @Override public void debug(final Player player, final String message) { CheckUtils.debug(player, type, message); } }