From 41e9d89efab24a8ddb15eeba8b11c4467f367848 Mon Sep 17 00:00:00 2001 From: asofold Date: Mon, 5 Jan 2015 16:12:05 +0100 Subject: [PATCH] Add info about version-dependent features to the "ncp version" command. * Add methods to NoCheatPlusAPI to add/set/get version tags. * Display all tags in the ncp reload command. * Alter test framework to set a dummy API. * Add tags for blocks, net checks, FastConsume. --- .../net/protocollib/ProtocolLibComponent.java | 1 + .../command/admin/VersionCommand.java | 16 +- .../init/vanilla/VanillaBlocksFactory.java | 10 +- .../components/NoCheatPlusAPI.java | 34 +++- .../utilities/BlockProperties.java | 10 +- .../neatmonster/nocheatplus/NoCheatPlus.java | 52 +++++-- .../compat/DefaultComponentFactory.java | 3 + .../neatmonster/nocheatplus/PluginTests.java | 146 ++++++++++++++++++ .../nocheatplus/test/BlockTests.java | 17 +- 9 files changed, 265 insertions(+), 24 deletions(-) create mode 100644 NCPPlugin/src/test/java/fr/neatmonster/nocheatplus/PluginTests.java diff --git a/NCPCompatProtocolLib/src/main/java/fr/neatmonster/nocheatplus/net/protocollib/ProtocolLibComponent.java b/NCPCompatProtocolLib/src/main/java/fr/neatmonster/nocheatplus/net/protocollib/ProtocolLibComponent.java index ac12102a..36256214 100644 --- a/NCPCompatProtocolLib/src/main/java/fr/neatmonster/nocheatplus/net/protocollib/ProtocolLibComponent.java +++ b/NCPCompatProtocolLib/src/main/java/fr/neatmonster/nocheatplus/net/protocollib/ProtocolLibComponent.java @@ -48,6 +48,7 @@ public class ProtocolLibComponent implements DisableListener, INotifyReload{ names.add(adapter.getClass().getSimpleName()); } StaticLog.logInfo("[NoCheatPlus] Available (and activated) packet level hooks: " + StringUtil.join(names, " | ")); + NCPAPIProvider.getNoCheatPlusAPI().addFeatureTags("checks", names); } } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/command/admin/VersionCommand.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/command/admin/VersionCommand.java index 46abe606..4fe0c911 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/command/admin/VersionCommand.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/command/admin/VersionCommand.java @@ -4,6 +4,9 @@ import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import org.bukkit.Bukkit; import org.bukkit.command.Command; @@ -36,7 +39,18 @@ public class VersionCommand extends BaseCommand{ "Plugin: " + access.getDescription().getVersion(), "MCAccess: " + mc.getMCVersion() + " / " + mc.getServerVersionTag(), }); - + final Map> featureTags = NCPAPIProvider.getNoCheatPlusAPI().getAllFeatureTags(); + if (!featureTags.isEmpty()) { + final List features = new LinkedList(); + // Add present features. + for (final Entry> entry : featureTags.entrySet()) { + features.add(" " + entry.getKey() + ": " + StringUtil.join(entry.getValue(), " | ")); + } + // Sort and add. + Collections.sort(features, String.CASE_INSENSITIVE_ORDER); + features.add(0, "Features:"); + sender.sendMessage(features.toArray(new String[features.size()])); + } final Collection hooks = NCPHookManager.getAllHooks(); if (!hooks.isEmpty()){ final List fullNames = new LinkedList(); diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/init/vanilla/VanillaBlocksFactory.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/init/vanilla/VanillaBlocksFactory.java index 53cc92c6..90369e05 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/init/vanilla/VanillaBlocksFactory.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/init/vanilla/VanillaBlocksFactory.java @@ -1,5 +1,6 @@ package fr.neatmonster.nocheatplus.compat.blocks.init.vanilla; +import java.util.Collection; import java.util.LinkedList; import java.util.List; @@ -7,12 +8,12 @@ import fr.neatmonster.nocheatplus.compat.blocks.BlockPropertiesSetup; import fr.neatmonster.nocheatplus.config.WorldConfigProvider; import fr.neatmonster.nocheatplus.logging.StaticLog; -public class VanillaBlocksFactory implements BlockPropertiesSetup{ +public class VanillaBlocksFactory { - @Override - public void setupBlockProperties(final WorldConfigProvider worldConfigProvider) { + public Collection setupVanillaBlocks(final WorldConfigProvider worldConfigProvider) { // Standard setups (abort with first failure, low to high MC version). final List setups = new LinkedList(); + final List success = new LinkedList(); try{ setups.add(new BlocksMC1_5()); setups.add(new BlocksMC1_6_1()); @@ -24,6 +25,8 @@ public class VanillaBlocksFactory implements BlockPropertiesSetup{ try{ // Assume the blocks setup to message success. setup.setupBlockProperties(worldConfigProvider); + success.add(setup.getClass().getSimpleName()); + // TODO: Do logging from here ? } catch(Throwable t){ StaticLog.logSevere("[NoCheatPlus] " + setup.getClass().getSimpleName() + ".setupBlockProperties could not execute properly: " + t.getClass().getSimpleName() + " - " + t.getMessage()); @@ -32,6 +35,7 @@ public class VanillaBlocksFactory implements BlockPropertiesSetup{ break; } } + return success; } } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/components/NoCheatPlusAPI.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/components/NoCheatPlusAPI.java index 02e5b7bf..d7e59c1a 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/components/NoCheatPlusAPI.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/components/NoCheatPlusAPI.java @@ -1,5 +1,9 @@ package fr.neatmonster.nocheatplus.components; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + import fr.neatmonster.nocheatplus.logging.LogManager; @@ -23,10 +27,36 @@ public interface NoCheatPlusAPI extends ComponentRegistry, ComponentRegi /** * By default addComponent(Object) will register ComponentFactories as well. * @param obj - * @param allowComponentRegistry If to allow registering ComponentFactories. + * @param allowComponentFactory If to allow registering ComponentFactories. * @return */ - public boolean addComponent(Object obj, boolean allowComponentRegistry); + public boolean addComponent(Object obj, boolean allowComponentFactory); + + /** + * Tell NCP that certain features are present, e.g. for display with the + * "ncp version" command. Version tags get cleared with disabling the + * plugin. + * + * @param key + * @param featureTags + */ + public void addFeatureTags(String key, Collection featureTags); + + /** + * Tell NCP that certain features are present, e.g. for display with the + * "ncp version" command. Overrides all present definitions for the given + * key. Version tags get cleared with disabling the plugin. + * + * @param key + * @param featureTags + */ + public void setFeatureTags(String key, Collection featureTags); + + /** + * Get a map with all feature tags that have been set. + * @return + */ + public Map> getAllFeatureTags(); /** * Send all players with the nocheatplus.admin.notify permission a message.
diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockProperties.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockProperties.java index 5da41750..28652a06 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockProperties.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockProperties.java @@ -6,10 +6,12 @@ import java.util.Arrays; import java.util.Collection; import java.util.InputMismatchException; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -21,6 +23,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffectType; +import fr.neatmonster.nocheatplus.NCPAPIProvider; import fr.neatmonster.nocheatplus.compat.MCAccess; import fr.neatmonster.nocheatplus.compat.blocks.BlockPropertiesSetup; import fr.neatmonster.nocheatplus.compat.blocks.init.vanilla.VanillaBlocksFactory; @@ -420,12 +423,14 @@ public class BlockProperties { public static void init(final MCAccess mcAccess, final WorldConfigProvider worldConfigProvider) { blockCache = mcAccess.getBlockCache(null); pLoc = new PlayerLocation(mcAccess, null); + final Set blocksFeatures = new LinkedHashSet(); // getClass().getName() or some abstract. try{ initTools(mcAccess, worldConfigProvider); initBlocks(mcAccess, worldConfigProvider); + blocksFeatures.add("BlocksMC1_4(base)"); // Extra hand picked setups. try{ - new VanillaBlocksFactory().setupBlockProperties(worldConfigProvider); + blocksFeatures.addAll(new VanillaBlocksFactory().setupVanillaBlocks(worldConfigProvider)); } catch(Throwable t) { StaticLog.logSevere("[NoCheatPlus] Could not initialize vanilla blocks: " + t.getClass().getSimpleName() + " - " + t.getMessage()); @@ -435,6 +440,7 @@ public class BlockProperties { if (mcAccess instanceof BlockPropertiesSetup) { try{ ((BlockPropertiesSetup) mcAccess).setupBlockProperties(worldConfigProvider); + blocksFeatures.add(mcAccess.getClass().getSimpleName()); } catch(Throwable t) { StaticLog.logSevere("[NoCheatPlus] McAccess.setupBlockProperties (" + mcAccess.getClass().getSimpleName() + ") could not execute properly: " + t.getClass().getSimpleName() + " - " + t.getMessage()); @@ -446,6 +452,8 @@ public class BlockProperties { catch(Throwable t) { StaticLog.logSevere(t); } + // Override feature tags for blocks. + NCPAPIProvider.getNoCheatPlusAPI().setFeatureTags("blocks", blocksFeatures); } private static void initTools(final MCAccess mcAccess, final WorldConfigProvider worldConfigProvider) { diff --git a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/NoCheatPlus.java b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/NoCheatPlus.java index 8e875fc6..a1d6cb78 100644 --- a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/NoCheatPlus.java +++ b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/NoCheatPlus.java @@ -5,6 +5,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; @@ -106,7 +107,7 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI { } // Not static. - + /** Central logging access point. */ private BukkitLogManager logManager = null; // Not final, but intended to stay, once set [change to init=syso?]. @@ -179,6 +180,9 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI { /** All registered components. */ protected Set allComponents = new LinkedHashSet(50); + /** Feature tags by keys, for features that might not be available. */ + private final LinkedHashMap> featureTags = new LinkedHashMap>(); + /** Tick listener that is only needed sometimes (component registration). */ protected final OnDemandTickListener onDemandTickListener = new OnDemandTickListener() { @Override @@ -634,6 +638,8 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI { subComponentholders.clear(); // Generic instances registry. genericInstances.clear(); + // Feature tags. + featureTags.clear(); // Clear command changes list (compatibility issues with NPCs, leads to recalculation of perms). if (changedCommands != null){ @@ -734,10 +740,10 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI { TickTask.purge(); TickTask.cancel(); TickTask.reset(); - + // Allow entries to TickTask (just in case). TickTask.setLocked(false); - + // Initialize configuration, if needed. if (!ConfigManager.isInitialized()) { // Read the configuration files (should only happen on reloading). @@ -745,13 +751,13 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI { } final ConfigFile config = ConfigManager.getConfigFile(); - + useSubscriptions = config.getBoolean(ConfPaths.LOGGING_BACKEND_INGAMECHAT_SUBSCRIPTIONS); - + // Start logger task(s). logManager.startTasks(); - - + + manageListeners = config.getBoolean(ConfPaths.COMPATIBILITY_MANAGELISTENERS); if (manageListeners) { listenerManager.setRegisterDirectly(true); @@ -776,7 +782,7 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI { // Initialize data manager. disableListeners.add(0, dataMan); dataMan.onEnable(); - + // Register components. @SetupOrder(priority = - 100) class ReloadHook implements INotifyReload{ @@ -896,7 +902,7 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI { ); } }); - + // Set StaticLog to more efficient output. StaticLog.setStreamID(Streams.STATUS); // Tell the server administrator that we finished loading NoCheatPlus now. @@ -963,7 +969,7 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI { // Cache some things. useSubscriptions = config.getBoolean(ConfPaths.LOGGING_BACKEND_INGAMECHAT_SUBSCRIPTIONS); } - + @Override public LogManager getLogManager() { return logManager; @@ -1251,4 +1257,30 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI { return registered; } + @Override + public void addFeatureTags(String key, Collection featureTags) { + LinkedHashSet present = this.featureTags.get(key); + if (present == null) { + present = new LinkedHashSet(); + this.featureTags.put(key, present); + } + present.addAll(featureTags); + } + + @Override + public void setFeatureTags(String key, Collection featureTags) { + LinkedHashSet present = new LinkedHashSet(); + this.featureTags.put(key, present); + present.addAll(featureTags); + } + + @Override + public Map> getAllFeatureTags() { + final LinkedHashMap> allTags = new LinkedHashMap>(); + for (final Entry> entry : this.featureTags.entrySet()) { + allTags.put(entry.getKey(), Collections.unmodifiableSet(entry.getValue())); + } + return Collections.unmodifiableMap(allTags); + } + } diff --git a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/compat/DefaultComponentFactory.java b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/compat/DefaultComponentFactory.java index a1c7d565..eedd7016 100644 --- a/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/compat/DefaultComponentFactory.java +++ b/NCPPlugin/src/main/java/fr/neatmonster/nocheatplus/compat/DefaultComponentFactory.java @@ -1,9 +1,11 @@ package fr.neatmonster.nocheatplus.compat; +import java.util.Arrays; import java.util.Collection; import java.util.LinkedList; 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.logging.StaticLog; @@ -30,6 +32,7 @@ public class DefaultComponentFactory { // TODO: Static test methods !? FastConsume.testAvailability(); available.add(new FastConsume()); + NCPAPIProvider.getNoCheatPlusAPI().addFeatureTags("checks", Arrays.asList(FastConsume.class.getSimpleName())); } catch (Throwable t){ StaticLog.logInfo("[NoCheatPlus] Inventory checks: FastConsume is not available."); diff --git a/NCPPlugin/src/test/java/fr/neatmonster/nocheatplus/PluginTests.java b/NCPPlugin/src/test/java/fr/neatmonster/nocheatplus/PluginTests.java new file mode 100644 index 00000000..bc12afef --- /dev/null +++ b/NCPPlugin/src/test/java/fr/neatmonster/nocheatplus/PluginTests.java @@ -0,0 +1,146 @@ +package fr.neatmonster.nocheatplus; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import fr.neatmonster.nocheatplus.compat.MCAccess; +import fr.neatmonster.nocheatplus.compat.bukkit.MCAccessBukkit; +import fr.neatmonster.nocheatplus.components.ComponentRegistry; +import fr.neatmonster.nocheatplus.components.NoCheatPlusAPI; +import fr.neatmonster.nocheatplus.logging.LogManager; +import fr.neatmonster.nocheatplus.logging.StaticLog; + +public class PluginTests { + + /** + * Dummy API, providing only a minimal subset of functionality for offline-testing. Some methods do nothing, some throw an UnsupportedOperationException, some will do something (set/get MCAccess). + * @author web4web1 + * + */ + public static class DummyNoCheatPlusAPI implements NoCheatPlusAPI { + + private MCAccess mcAccess = new MCAccessBukkit(); + + @Override + public void setMCAccess(MCAccess mcAccess) { + this.mcAccess = mcAccess; + } + + @Override + public MCAccess getMCAccess() { + return mcAccess; + } + + @Override + public boolean addComponent(Object component) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeComponent(Object component) { + throw new UnsupportedOperationException(); + } + + @Override + public Collection> getComponentRegistries(Class> clazz) { + throw new UnsupportedOperationException(); + } + + @Override + public T registerGenericInstance(T instance) { + throw new UnsupportedOperationException(); + } + + @Override + public T registerGenericInstance(Class registerFor, TI instance) { + throw new UnsupportedOperationException(); + } + + @Override + public T getGenericInstance(Class registeredFor) { + throw new UnsupportedOperationException(); + } + + @Override + public T unregisterGenericInstance(Class registeredFor) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addComponent(Object obj, boolean allowComponentFactory) { + throw new UnsupportedOperationException(); + } + + @Override + public void addFeatureTags(String key, Collection featureTags) { + // IGNORE + } + + @Override + public void setFeatureTags(String key, Collection featureTags) { + // IGNORE + } + + @Override + public Map> getAllFeatureTags() { + throw new UnsupportedOperationException(); + } + + @Override + public int sendAdminNotifyMessage(String message) { + StaticLog.logInfo("AdminNotifyMessage: " + message); + return 1; + } + + @Override + public void sendMessageOnTick(String playerName, String message) { + StaticLog.logInfo("sendMessageOnTick (-> " + playerName + "): " + message); + } + + @Override + public boolean allowLogin(String playerName) { + throw new UnsupportedOperationException(); + } + + @Override + public int allowLoginAll() { + throw new UnsupportedOperationException(); + } + + @Override + public void denyLogin(String playerName, long duration) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isLoginDenied(String playerName) { + throw new UnsupportedOperationException(); + } + + @Override + public String[] getLoginDeniedPlayers() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isLoginDenied(String playerName, long time) { + throw new UnsupportedOperationException(); + } + + @Override + public LogManager getLogManager() { + // TODO: Maybe do implement a dummy log manager (with file?) + throw new UnsupportedOperationException(); + } + + + } + + public static void setDummNoCheatPlusAPI(boolean force) { + if (force || NCPAPIProvider.getNoCheatPlusAPI() == null) { + NCPAPIProvider.setNoCheatPlusAPI(new DummyNoCheatPlusAPI()); + } + } + +} diff --git a/NCPPlugin/src/test/java/fr/neatmonster/nocheatplus/test/BlockTests.java b/NCPPlugin/src/test/java/fr/neatmonster/nocheatplus/test/BlockTests.java index 558039ba..e8823864 100644 --- a/NCPPlugin/src/test/java/fr/neatmonster/nocheatplus/test/BlockTests.java +++ b/NCPPlugin/src/test/java/fr/neatmonster/nocheatplus/test/BlockTests.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import fr.neatmonster.nocheatplus.NCPAPIProvider; +import fr.neatmonster.nocheatplus.PluginTests; import fr.neatmonster.nocheatplus.compat.bukkit.MCAccessBukkit; import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.DefaultConfig; @@ -17,9 +19,9 @@ import fr.neatmonster.nocheatplus.utilities.BlockProperties; * */ public class BlockTests { - + public static class SimpleWorldConfigProvider implements WorldConfigProvider { - + private final C config; public SimpleWorldConfigProvider(C config) { @@ -42,20 +44,21 @@ public class BlockTests { list.add(config); return list; } - + } - + public static class DefaultConfigWorldConfigProvider extends SimpleWorldConfigProvider { public DefaultConfigWorldConfigProvider() { super(new DefaultConfig()); } } - + /** * Initialize BlockProperties with default config and Bukkit-API compliance :p. */ public static void initBlockProperties() { - BlockProperties.init(new MCAccessBukkit(), new DefaultConfigWorldConfigProvider()); + PluginTests.setDummNoCheatPlusAPI(false); + BlockProperties.init(NCPAPIProvider.getNoCheatPlusAPI().getMCAccess(), new DefaultConfigWorldConfigProvider()); } - + }