Add Minecraft version detection and version-dependent default values.

We can now decide on base of the Minecraft version, which value to use,
with the config entry set to "default". Used with
pvp-knock-back-velocity and enforce-location (first move exploit).

Activated features are shown in the version info ("ncp version"). The
version info is now logged to the log file after post-enable and after
reloading the configuration.
This commit is contained in:
asofold 2015-01-11 18:52:08 +01:00
parent 02a95f6cab
commit d2da3f1e9e
14 changed files with 685 additions and 142 deletions

View File

@ -10,6 +10,8 @@ import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.ACheckConfig;
import fr.neatmonster.nocheatplus.checks.access.CheckConfigFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckConfig;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.versions.Bugs;
import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.ConfigManager;
@ -177,7 +179,8 @@ public class FightConfig extends ACheckConfig {
yawRateCheck = data.getBoolean(ConfPaths.FIGHT_YAWRATE_CHECK, true);
cancelDead = data.getBoolean(ConfPaths.FIGHT_CANCELDEAD);
knockBackVelocityPvP = data.getBoolean(ConfPaths.FIGHT_PVP_KNOCKBACKVELOCITY);
AlmostBoolean ref = data.getAlmostBoolean(ConfPaths.FIGHT_PVP_KNOCKBACKVELOCITY, AlmostBoolean.MAYBE);
knockBackVelocityPvP = ref == AlmostBoolean.MAYBE ? Bugs.shouldPvpKnockBackVelocity() : ref.decide();
}
/* (non-Javadoc)

View File

@ -11,6 +11,8 @@ import fr.neatmonster.nocheatplus.checks.access.ACheckConfig;
import fr.neatmonster.nocheatplus.checks.access.CheckConfigFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckConfig;
import fr.neatmonster.nocheatplus.command.CommandUtil;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.versions.Bugs;
import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.ConfigManager;
@ -244,9 +246,15 @@ public class MovingConfig extends ACheckConfig {
sprintingGrace = Math.max(0L, (long) (config.getDouble(ConfPaths.MOVING_SPRINTINGGRACE) * 1000.0)); // Config: seconds.
assumeSprint = config.getBoolean(ConfPaths.MOVING_ASSUMESPRINT);
speedGrace = Math.max(0, (int) Math.round(config.getDouble(ConfPaths.MOVING_SPEEDGRACE) * 20.0)); // Config: seconds
enforceLocation = config.getBoolean(ConfPaths.MOVING_ENFORCELOCATION);
AlmostBoolean ref = config.getAlmostBoolean(ConfPaths.MOVING_ENFORCELOCATION, AlmostBoolean.MAYBE);
if (ref == AlmostBoolean.MAYBE) {
enforceLocation = Bugs.shouldEnforceLocation();
} else {
enforceLocation = ref.decide();
}
vehicleEnforceLocation = config.getBoolean(ConfPaths.MOVING_VEHICLES_ENFORCELOCATION);
ref = config.getAlmostBoolean(ConfPaths.MOVING_VEHICLES_ENFORCELOCATION, AlmostBoolean.MAYBE);
vehicleEnforceLocation = ref.decideOptimistically(); // Currently rather enabled.
vehiclePreventDestroyOwn = config.getBoolean(ConfPaths.MOVING_VEHICLES_PREVENTDESTROYOWN);
traceSize = config.getInt(ConfPaths.MOVING_TRACE_SIZE);

View File

@ -19,6 +19,7 @@ import fr.neatmonster.nocheatplus.logging.LogManager;
import fr.neatmonster.nocheatplus.logging.Streams;
import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.utilities.StringUtil;
public class ReloadCommand extends BaseCommand {
@ -87,6 +88,7 @@ public class ReloadCommand extends BaseCommand {
sender.sendMessage(TAG + "Configuration reloaded!");
}
logManager.info(Streams.INIT, "[NoCheatPlus] Configuration reloaded.");
logManager.info(Streams.DEFAULT_FILE, StringUtil.join(VersionCommand.getVersionInfo(), "\n")); // Queued (!).
}
}

View File

@ -1,5 +1,6 @@
package fr.neatmonster.nocheatplus.command.admin;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
@ -16,6 +17,7 @@ import org.bukkit.plugin.java.JavaPlugin;
import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.command.BaseCommand;
import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
import fr.neatmonster.nocheatplus.hooks.NCPHook;
import fr.neatmonster.nocheatplus.hooks.NCPHookManager;
import fr.neatmonster.nocheatplus.permissions.Permissions;
@ -28,17 +30,24 @@ public class VersionCommand extends BaseCommand{
}
@Override
public boolean onCommand(CommandSender sender, Command command,
String label, String[] args) {
final MCAccess mc = NCPAPIProvider.getNoCheatPlusAPI().getMCAccess();
sender.sendMessage(new String[]{
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
List<String> lines = getVersionInfo();
sender.sendMessage(lines.toArray(new String[lines.size()]));
return true;
}
public static List<String> getVersionInfo() {
final List<String> lines = new LinkedList<String>();
final MCAccess mcAccess = NCPAPIProvider.getNoCheatPlusAPI().getMCAccess();
lines.addAll(Arrays.asList(new String[]{
"---- Version information ----",
"#### Server ####",
Bukkit.getServer().getVersion(),
"(detected: " + ServerVersion.getMinecraftVersion() + ")",
"#### NoCheatPlus ####",
"Plugin: " + access.getDescription().getVersion(),
"MCAccess: " + mc.getMCVersion() + " / " + mc.getServerVersionTag(),
});
"Plugin: " + Bukkit.getPluginManager().getPlugin("NoCheatPlus").getDescription().getVersion(),
"MCAccess: " + mcAccess.getMCVersion() + " / " + mcAccess.getServerVersionTag(),
}));
final Map<String, Set<String>> featureTags = NCPAPIProvider.getNoCheatPlusAPI().getAllFeatureTags();
if (!featureTags.isEmpty()) {
final List<String> features = new LinkedList<String>();
@ -49,7 +58,7 @@ public class VersionCommand extends BaseCommand{
// Sort and add.
Collections.sort(features, String.CASE_INSENSITIVE_ORDER);
features.add(0, "Features:");
sender.sendMessage(features.toArray(new String[features.size()]));
lines.addAll(features);
}
final Collection<NCPHook> hooks = NCPHookManager.getAllHooks();
if (!hooks.isEmpty()){
@ -58,9 +67,9 @@ public class VersionCommand extends BaseCommand{
fullNames.add(hook.getHookName() + " " + hook.getHookVersion());
}
Collections.sort(fullNames, String.CASE_INSENSITIVE_ORDER);
sender.sendMessage("Hooks: " + StringUtil.join(fullNames, " | "));
lines.add("Hooks: " + StringUtil.join(fullNames, " | "));
}
return true;
return lines;
}
}

View File

@ -19,6 +19,29 @@ public enum AlmostBoolean{
return value ? YES : NO;
}
/**
* Match yes/true/y, no/false/n, maybe/default, otherwise returns null.
* @param input Can be null.
* @return
*/
public static final AlmostBoolean match(String input) {
if (input == null) {
return null;
}
input = input.trim().toLowerCase();
if (input.equals("true") || input.equals("yes") || input.equals("y")) {
return AlmostBoolean.YES;
}
else if (input.equals("false") || input.equals("no") || input.equals("n")) {
return AlmostBoolean.NO;
}
else if (input.equals("default") || input.equals("maybe")) {
return AlmostBoolean.MAYBE;
} else {
return null;
}
}
/**
* Pessimistic interpretation: true iff YES.
* @return

View File

@ -0,0 +1,69 @@
package fr.neatmonster.nocheatplus.compat.versions;
import java.util.LinkedList;
import java.util.List;
import org.bukkit.Bukkit;
import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.components.NoCheatPlusAPI;
/**
* Feature selection, based on the version.
* @author web4web1
*
*/
public class Bugs {
private static boolean enforceLocation = false;
private static boolean pvpKnockBackVelocity = false;
protected static void init() {
final String mcVersion = ServerVersion.getMinecraftVersion();
final String serverVersion = Bukkit.getServer().getVersion().toLowerCase();
final NoCheatPlusAPI api = NCPAPIProvider.getNoCheatPlusAPI();
final List<String> noteWorthy = new LinkedList<String>();
// Need to add velocity (only internally) because the server does not.
pvpKnockBackVelocity = ServerVersion.select("1.8", false, true, true, false);
if (pvpKnockBackVelocity) {
noteWorthy.add("pvpKnockBackVelocity");
}
// First move exploit (classic CraftBukkit or Spigot before 1.7.5).
if (mcVersion == ServerVersion.UNKNOWN_VERSION) {
// Assume something where it's not an issue.
enforceLocation = false;
}
else if (ServerVersion.compareVersions(mcVersion, "1.8") >= 0) {
// Assume Spigot + fixed.
enforceLocation = false;
} else if (serverVersion.indexOf("spigot") >= 0 && ServerVersion.compareVersions(mcVersion, "1.7.5") >= 0) {
// Fixed in Spigot just before 1.7.5.
enforceLocation = false;
} else if (serverVersion.indexOf("craftbukkit") != 0){
// Assume classic CraftBukkit (not fixed).
enforceLocation = true;
} else {
// Assume something where it's not an issue.
enforceLocation = false;
}
if (enforceLocation) {
noteWorthy.add("enforceLocation");
}
if (!noteWorthy.isEmpty()) {
api.addFeatureTags("defaults", noteWorthy); // Not sure how to name these.
// Consider Bukkit.getLogger, or put to status after post-enable.
}
}
public static boolean shouldEnforceLocation() {
return enforceLocation;
}
public static boolean shouldPvpKnockBackVelocity() {
return pvpKnockBackVelocity;
}
}

View File

@ -0,0 +1,93 @@
package fr.neatmonster.nocheatplus.compat.versions;
import org.bukkit.Bukkit;
import org.bukkit.Server;
/**
* Bukkit-specific static access API, adding initialization methods. Note that Bukkit.getVersion() should be used to get the version of Bukkit (...).
* <hr/>
* Taken from the TrustCore plugin.
* @author mc_dev
*
*/
public class BukkitVersion {
private static boolean initialized = false;
private static boolean uniqueIdOnline = false;
private static boolean uniqueIdOffline = false;
/**
* Initialize ServerVersion, BukkitVersion, Bugs.
*/
public static boolean init() {
if (initialized) {
return false;
}
// Initialize server version.
final Server server = Bukkit.getServer();
ServerVersion.setMinecraftVersion(ServerVersion.parseMinecraftVersion(server.getBukkitVersion(), server.getVersion()));
// Test availability/reliability of certain features.
boolean uuidOnline = false;
boolean uuidOffline = false;
// TODO: Check for some versions explicitly.
String mcVersion = ServerVersion.getMinecraftVersion();
int cmp = -1;
try {
cmp = ServerVersion.compareVersions(mcVersion, "1.7.5");
} catch (IllegalArgumentException e) {
mcVersion = ServerVersion.UNKNOWN_VERSION; // Fake but somewhat true :p.
}
if (ServerVersion.UNKNOWN_VERSION.equals(mcVersion)) {
// TODO: Might test for features.
} else if (cmp == 1) {
uuidOnline = true;
uuidOffline = true;
} else if (ServerVersion.compareVersions(mcVersion, "1.7") == 1) {
// 1.7.x
uuidOnline = true; // TODO: Test, if REALLY.
uuidOffline = false;
}
uniqueIdOnline = uuidOnline;
uniqueIdOffline = uuidOffline;
initialized = true;
Bugs.init();
return true;
}
/**
* Test if Player.getUniqueId be used for online players.
* @return
*/
public static boolean uniqueIdOnline() {
return uniqueIdOnline;
}
public static void setUniqueIdOnline(boolean uniqueIdOnline) {
BukkitVersion.uniqueIdOnline = uniqueIdOnline;
}
/**
* Test if OfflinePlayer.getUniqueId can be used for offline payers [provided it exists :p].<br>
* Not sure this makes sense :p.
* <hr>
* IMPORTANT NOTE: DO NOT MIX UP WITH OFFLINE MODE!<br>
* @return
*/
public static boolean uniqueIdOffline() {
return uniqueIdOffline;
}
public static void setUniqueIdOffline(boolean uniqueIdOffline) {
BukkitVersion.uniqueIdOffline = uniqueIdOffline;
}
/**
* Delegating to ServerVersion.getMinecraftVersion.
* @return
*/
public static String getMinecraftVersion() {
return ServerVersion.getMinecraftVersion();
}
}

View File

@ -0,0 +1,233 @@
package fr.neatmonster.nocheatplus.compat.versions;
/**
* Static utility that stores the Minecraft version, providing some parsing methods.
* This has to be initialized from an external source (e.g. a plugin calling BukkitVersion.init).
* <hr/>
* Taken from the TrustCore plugin.
* @author mc_dev
*
*/
public class ServerVersion {
public static final String UNKNOWN_VERSION = "unknown";
private static String minecraftVersion = UNKNOWN_VERSION;
private static final String[][] versionTagsMatch = {
{"1.7.2-r", "1.7.2"}, // Example. Probably this method will just be removed.
};
/**
* Attempt to return the Minecraft version for a given server version string.
* @param serverVersion As returned by Bukkit.getServer().getVersion();
* @return null if not known/parsable.
*/
public static String parseMinecraftVersion(String... versionCandidates) {
for (String serverVersion : versionCandidates) {
for (String minecraftVersion : new String[]{
collectVersion(serverVersion, 0),
parseMinecraftVersionGeneric(serverVersion),
parseMinecraftVersionTokens(serverVersion)
}) {
// Validate if not null, might mean double validation.
if (minecraftVersion != null && validateMinecraftVersion(minecraftVersion)) {
return minecraftVersion;
}
}
}
return null;
}
/**
* Simple consistency check.
* @param minecraftVersion
* @return
*/
private static boolean validateMinecraftVersion(String minecraftVersion) {
return collectVersion(minecraftVersion, 0) != null;
}
/**
* Match directly versus hard coded examples. Not for direct use.
* @param serverVersion
* @return
*/
private static String parseMinecraftVersionTokens(String serverVersion) {
serverVersion = serverVersion.trim().toLowerCase();
for (String[] entry : versionTagsMatch) {
if (serverVersion.contains(entry[0])) {
return entry[1];
}
}
return null;
}
/**
* Collect a version of the type X.Y.Z with X, Y, Z being numbers. Demands at least one number,
* but allows an arbitrary amount of sections X....Y. Rigid character check, probably not fit for snapshots.
* @param input
* @param beginIndex
* @return null if not successful.
*/
private static String collectVersion(String input, int beginIndex) {
StringBuilder buffer = new StringBuilder(128);
// Rigid scan by character.
boolean numberFound = false;
char[] chars = input.toCharArray();
for (int i = beginIndex; i < input.length(); i++) {
char c = chars[i];
if (c == '.') {
if (numberFound) {
// Reset, expecting a number to follow.
numberFound = false;
} else {
// Failure.
return null;
}
} else if (!Character.isDigit(c)) {
// Failure.
return null;
} else {
numberFound = true;
}
buffer.append(c);
}
if (numberFound) {
return buffer.toString();
} else {
return null;
}
}
/**
*
* @param serverVersion
* @return
*/
private static String parseMinecraftVersionGeneric(String serverVersion) {
String lcServerVersion = serverVersion.trim().toLowerCase();
for (String candidate : new String[] {
// git-bukkit-MC_VERSION-rX.Y
parseVersionDelimiters(lcServerVersion, "git-bukkit-", "-r"),
parseVersionDelimiters(lcServerVersion, "", "-r"),
// TODO: Other server mods + custom builds !?.
}) {
if (candidate != null) {
return candidate;
}
}
return null;
}
/**
* Exact case, no trim.
* @param input
* @param prefix
* @param suffix
* @return
*/
private static String parseVersionDelimiters(String input, String prefix, String suffix) {
int preIndex = prefix.isEmpty() ? 0 : input.indexOf(prefix);
if (preIndex != -1) {
String candidate = input.substring(preIndex + prefix.length());
int postIndex = suffix.isEmpty() ? candidate.length() : candidate.indexOf(suffix);
if (postIndex != -1) {
return collectVersion(candidate.substring(0, postIndex), 0);
}
}
return null;
}
/**
* Sets lower-case Minecraft version - or UNKNOWN_VERSION, if null or empty.
* @param version Can be null (resulting in UNKNOWN_VERSION).
* @return The String that minecraftVersion has been set to.
*/
public static String setMinecraftVersion(String version) {
if (version == null) {
minecraftVersion = UNKNOWN_VERSION;
} else {
version = version.trim().toLowerCase();
if (version.isEmpty()) {
minecraftVersion = UNKNOWN_VERSION;
} else {
minecraftVersion = version;
}
}
return minecraftVersion;
}
/**
*
* @return Some version string, or UNKNOWN_VERSION.
*/
public static String getMinecraftVersion() {
return minecraftVersion;
}
/**
* Simple x.y.z versions. Returns 0 on equality, -1 if version 1 is smaller than version 2, 1 if version 1 is greater than version 2.
* @param version1 Can be unknown.
* @param version2 Must not be unknown.
* @return
*/
public static int compareVersions(String version1, String version2) {
if (version2.equals(UNKNOWN_VERSION)) {
throw new IllegalArgumentException("version2 must not be 'unknown'.");
} else if (version1.equals(UNKNOWN_VERSION)) {
// Assume smaller than any given version.
return -1;
}
if (version1.equals(version2)) {
return 0;
}
try {
int[] v1Int = versionToInt(version1);
int[] v2Int = versionToInt(version2);
for (int i = 0; i < Math.min(v1Int.length, v2Int.length); i++) {
if (v1Int[i] < v2Int[i]) {
return -1;
} else if (v1Int[i] > v2Int[i]) {
return 1;
}
}
// Support sub-sub-sub-...-....-marines.
if (v1Int.length < v2Int.length) {
return -1;
}
else if (v1Int.length > v2Int.length) {
return 1;
}
} catch (NumberFormatException e) {}
// Equality was tested above, so it would seem.
throw new IllegalArgumentException("Bad version input.");
}
public static int[] versionToInt(String version) {
String[] split = version.split("\\.");
int[] num = new int[split.length];
for (int i = 0; i < split.length; i++) {
num[i] = Integer.parseInt(split[i]);
}
return num;
}
public static <V> V select(final String cmpVersion, final V valueLT, final V valueEQ, final V valueGT, final V valueUnknown) {
final String mcVersion = ServerVersion.getMinecraftVersion();
if (mcVersion == ServerVersion.UNKNOWN_VERSION) {
return valueUnknown;
} else {
final int cmp = ServerVersion.compareVersions(mcVersion, cmpVersion);
if (cmp == 0) {
return valueEQ;
} else if (cmp < 0) {
return valueLT;
} else {
return valueGT;
}
}
}
}

View File

@ -13,10 +13,11 @@ import org.bukkit.Material;
public class DefaultConfig extends ConfigFile {
/**
* NCP build needed for this config.
* (Should only increment with changing or removing paths.)
* NCP build number, for which an existing entry has been changed. (Should
* only increment, if the user is advised to change to that value instead of
* the former default one.)
*/
public static final int buildNumber = 754;
public static final int buildNumber = 785;
// TODO: auto input full version or null to an extra variable or several [fail safe for other syntax checking]?
@ -262,7 +263,7 @@ public class DefaultConfig extends ConfigFile {
// FIGHT
set(ConfPaths.FIGHT_CANCELDEAD, true);
set(ConfPaths.FIGHT_TOOLCHANGEPENALTY, 500L);
set(ConfPaths.FIGHT_PVP_KNOCKBACKVELOCITY, true);
set(ConfPaths.FIGHT_PVP_KNOCKBACKVELOCITY, "default");
set(ConfPaths.FIGHT_YAWRATE_CHECK, true);
@ -413,7 +414,7 @@ public class DefaultConfig extends ConfigFile {
// Vehicles.
set(ConfPaths.MOVING_VEHICLES_PREVENTDESTROYOWN, true);
set(ConfPaths.MOVING_VEHICLES_ENFORCELOCATION, true);
set(ConfPaths.MOVING_VEHICLES_ENFORCELOCATION, "default");
// Velocity.
set(ConfPaths.MOVING_VELOCITY_GRACETICKS, 20);
@ -427,7 +428,7 @@ public class DefaultConfig extends ConfigFile {
set(ConfPaths.MOVING_SPRINTINGGRACE, 2.0);
set(ConfPaths.MOVING_ASSUMESPRINT, true);
set(ConfPaths.MOVING_SPEEDGRACE, 4.0);
set(ConfPaths.MOVING_ENFORCELOCATION, true);
set(ConfPaths.MOVING_ENFORCELOCATION, "default");
// NET

View File

@ -8,6 +8,8 @@ import org.bukkit.Material;
import org.bukkit.configuration.file.YamlConfiguration;
import org.yaml.snakeyaml.DumperOptions;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
import fr.neatmonster.nocheatplus.logging.StaticLog;
public class RawConfigFile extends YamlConfiguration{
@ -64,6 +66,19 @@ public class RawConfigFile extends YamlConfiguration{
// Not static.
////////////////
/**
* Set a value depending on the detected Minecraft version.
* @param path
* @param cmpVersion The version to compare to (N.N.N).
* @param valueLT Value to use if the detected version is smaller/less than the given one.
* @param valueEQ Value to use if the detected version is equal to the given one.
* @param valueGT Value to use if the detected version is greater than the detected one.
* @param valueUnknown Value to use if the version could not be detected (e.g. unknown format).
*/
public void setVersionDependent(final String path, final String cmpVersion, final Object valueLT, final Object valueEQ, final Object valueGT, final Object valueUnknown) {
set(path, ServerVersion.select(cmpVersion, valueLT, valueEQ, valueGT, valueUnknown));
}
/**
* Return a double value within given bounds, with preset.
*
@ -165,6 +180,11 @@ public class RawConfigFile extends YamlConfiguration{
}
}
public AlmostBoolean getAlmostBoolean(final String path, final AlmostBoolean defaultValue) {
final AlmostBoolean choice = AlmostBoolean.match(getString(path, null));
return choice == null ? defaultValue : choice;
}
/**
* Outputs warnings to console.
* @param path

View File

@ -0,0 +1,41 @@
package fr.neatmonster.nocheatplus;
import static org.junit.Assert.fail;
import org.junit.Test;
import fr.neatmonster.nocheatplus.utilities.IdUtil;
public class TestIdUtil {
@Test
public void testMinecraftUserNames() {
String[] valid = new String[] {
"xdxdxd",
"XDXDXD",
"sa_Sd_ASD"
};
for (String name : valid) {
if (!IdUtil.isValidMinecraftUserName(name)) {
fail("Expect user name to be valid: " + name);
}
}
String[] inValid = new String[] {
"xd xd xd",
"",
"x",
"0123456789abcdefX",
"*§$FUJAL"
};
for (String name : inValid) {
if (IdUtil.isValidMinecraftUserName(name)) {
fail("Expect user name to be invalid: " + name);
}
}
}
}

View File

@ -0,0 +1,30 @@
package fr.neatmonster.nocheatplus;
import static org.junit.Assert.fail;
import org.junit.Test;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
public class TestMinecraftVersion {
@Test
public void testParseMinecraftVersion() {
for (String[] pair : new String[][] {
{null, ""},
{"1.7.5", "1.7.5"},
{"1.7.5", "1.7.5-R0.1-SNAPSHOT"},
{"1.7.2", "git-Bukkit-1.7.2-R0.3-14-g8f8716c-b3042jnks"},
}) {
String parsed = ServerVersion.parseMinecraftVersion(pair[1]);
if (pair[0] == null) {
if (parsed != null) {
fail("Expect null output on: " + pair[1] + ", got instead: " + parsed);
}
} else if (!pair[0].equals(parsed)) {
fail("Expect " + pair[0] + " for input: " + pair[1] + ", got instead: " + parsed);
}
}
}
}

View File

@ -45,10 +45,13 @@ import fr.neatmonster.nocheatplus.checks.inventory.InventoryListener;
import fr.neatmonster.nocheatplus.checks.moving.MovingListener;
import fr.neatmonster.nocheatplus.clients.ModUtil;
import fr.neatmonster.nocheatplus.command.NoCheatPlusCommand;
import fr.neatmonster.nocheatplus.command.admin.VersionCommand;
import fr.neatmonster.nocheatplus.compat.BridgeMisc;
import fr.neatmonster.nocheatplus.compat.DefaultComponentFactory;
import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.compat.MCAccessFactory;
import fr.neatmonster.nocheatplus.compat.versions.BukkitVersion;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
import fr.neatmonster.nocheatplus.components.ComponentRegistry;
import fr.neatmonster.nocheatplus.components.ComponentWithName;
import fr.neatmonster.nocheatplus.components.ConsistencyChecker;
@ -86,6 +89,7 @@ import fr.neatmonster.nocheatplus.utilities.BlockProperties;
import fr.neatmonster.nocheatplus.utilities.ColorUtil;
import fr.neatmonster.nocheatplus.utilities.OnDemandTickListener;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.TickTask;
/**
@ -721,12 +725,14 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI {
public void onLoad() {
Bukkit.getLogger().info("[NoCheatPlus] Setting up static API, config, logging.");
NCPAPIProvider.setNoCheatPlusAPI(this);
BukkitVersion.init();
// Read the configuration files.
ConfigManager.init(this); // TODO: Only load the bootstrap config (not all).
logManager = new BukkitLogManager(this);
StaticLog.setStreamID(Streams.INIT);
StaticLog.setUseLogManager(true);
logManager.info(Streams.INIT, "[NoCheatPlus] Logging system initialized.");
logManager.info(Streams.INIT, "[NoCheatPlus] Detected Minecraft version: " + ServerVersion.getMinecraftVersion());
}
/* (non-Javadoc)
@ -932,6 +938,7 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI {
}
// TODO: if (online.lenght > 0) LogUtils.logInfo("[NCP] Updated " + online.length + "players (post-enable).")
logManager.info(Streams.INIT, "[NoCheatPlus] Post-enable finished.");
logManager.info(Streams.DEFAULT_FILE, StringUtil.join(VersionCommand.getVersionInfo(), "\n")); // Queued (!).
}
/**

View File

@ -8,6 +8,8 @@ import java.util.List;
import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.NoCheatPlus;
import fr.neatmonster.nocheatplus.checks.inventory.FastConsume;
import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.logging.StaticLog;
import fr.neatmonster.nocheatplus.net.protocollib.ProtocolLibComponent;
@ -32,8 +34,10 @@ public class DefaultComponentFactory {
// TODO: Static test methods !?
FastConsume.testAvailability();
available.add(new FastConsume());
if (ConfigManager.isTrueForAnyConfig(ConfPaths.INVENTORY_FASTCONSUME_CHECK)) {
NCPAPIProvider.getNoCheatPlusAPI().addFeatureTags("checks", Arrays.asList(FastConsume.class.getSimpleName()));
}
}
catch (Throwable t){
StaticLog.logInfo("[NoCheatPlus] Inventory checks: FastConsume is not available.");
}