diff options
Diffstat (limited to 'src/main')
15 files changed, 614 insertions, 68 deletions
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java index 5212f961..1b326a55 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -13,13 +13,14 @@ import org.bukkit.block.Block; import org.bukkit.entity.*; import org.bukkit.generator.BlockPopulator; import org.bukkit.inventory.ItemStack; +import org.bukkit.metadata.Metadatable; import org.bukkit.plugin.messaging.PluginMessageRecipient; import org.bukkit.util.Vector; /** * Represents a world, which may contain entities, chunks and blocks */ -public interface World extends PluginMessageRecipient { +public interface World extends PluginMessageRecipient, Metadatable { /** * Gets the {@link Block} at the given coordinates diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java index 7ca3c01b..99bc5630 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java @@ -7,6 +7,7 @@ import org.bukkit.Material; import org.bukkit.World; import org.bukkit.Location; import org.bukkit.inventory.ItemStack; +import org.bukkit.metadata.Metadatable; /** * Represents a block. This is a live object, and only one Block may exist for @@ -14,7 +15,7 @@ import org.bukkit.inventory.ItemStack; * to your own handling of it; use block.getState() to get a snapshot state of a * block which will not be modified. */ -public interface Block { +public interface Block extends Metadatable { /** * Gets the metadata for this block diff --git a/src/main/java/org/bukkit/block/BlockState.java b/src/main/java/org/bukkit/block/BlockState.java index 7e181017..cd5bcfbf 100644 --- a/src/main/java/org/bukkit/block/BlockState.java +++ b/src/main/java/org/bukkit/block/BlockState.java @@ -5,6 +5,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.material.MaterialData; +import org.bukkit.metadata.Metadatable; /** * Represents a captured state of a block, which will not change automatically. @@ -14,7 +15,7 @@ import org.bukkit.material.MaterialData; * the state of the block and you will not know, or they may change the block to * another type entirely, causing your BlockState to become invalid. */ -public interface BlockState { +public interface BlockState extends Metadatable { /** * Gets the block represented by this BlockState diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java index c8554734..d9d219b3 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java @@ -5,6 +5,7 @@ import org.bukkit.EntityEffect; import org.bukkit.Server; import org.bukkit.World; import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.metadata.Metadatable; import org.bukkit.util.Vector; import java.util.List; @@ -14,7 +15,7 @@ import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; /** * Represents a base entity in the world */ -public interface Entity { +public interface Entity extends Metadatable { /** * Gets the entity's current position diff --git a/src/main/java/org/bukkit/metadata/FixedMetadataValue.java b/src/main/java/org/bukkit/metadata/FixedMetadataValue.java new file mode 100644 index 00000000..41f89a0e --- /dev/null +++ b/src/main/java/org/bukkit/metadata/FixedMetadataValue.java @@ -0,0 +1,25 @@ +package org.bukkit.metadata; + +import org.bukkit.plugin.Plugin; + +import java.util.concurrent.Callable; + +/** + * A FixedMetadataValue is a special case metadata item that contains the same value forever after initialization. + * Invalidating a FixedMetadataValue has no affect. + */ +public class FixedMetadataValue extends LazyMetadataValue { + /** + * Initializes a FixedMetadataValue with an Object + * + * @param owningPlugin the {@link Plugin} that created this metadata value. + * @param value the value assigned to this metadata value. + */ + public FixedMetadataValue(Plugin owningPlugin, final Object value) { + super(owningPlugin, CacheStrategy.CACHE_ETERNALLY, new Callable<Object>() { + public Object call() throws Exception { + return value; + } + }); + } +} diff --git a/src/main/java/org/bukkit/metadata/LazyMetadataValue.java b/src/main/java/org/bukkit/metadata/LazyMetadataValue.java new file mode 100644 index 00000000..cc0ba506 --- /dev/null +++ b/src/main/java/org/bukkit/metadata/LazyMetadataValue.java @@ -0,0 +1,158 @@ +package org.bukkit.metadata; + +import java.lang.ref.SoftReference; +import java.util.concurrent.Callable; + +import org.apache.commons.lang.Validate; +import org.bukkit.plugin.Plugin; +import org.bukkit.util.NumberConversions; + +/** + * The LazyMetadataValue class implements a type of metadata that is not computed until another plugin asks for it. + * By making metadata values lazy, no computation is done by the providing plugin until absolutely necessary (if ever). + * Additionally, LazyMetadataValue objects cache their values internally unless overridden by a {@link CacheStrategy} + * or invalidated at the individual or plugin level. Once invalidated, the LazyMetadataValue will recompute its value + * when asked. + */ +public class LazyMetadataValue implements MetadataValue { + private Callable<Object> lazyValue; + private CacheStrategy cacheStrategy; + private SoftReference<Object> internalValue = new SoftReference<Object>(null); + private Plugin owningPlugin; + private static final Object ACTUALLY_NULL = new Object(); + + /** + * Initialized a LazyMetadataValue object with the default CACHE_AFTER_FIRST_EVAL cache strategy. + * + * @param owningPlugin the {@link Plugin} that created this metadata value. + * @param lazyValue the lazy value assigned to this metadata value. + */ + public LazyMetadataValue(Plugin owningPlugin, Callable<Object> lazyValue) { + this(owningPlugin, CacheStrategy.CACHE_AFTER_FIRST_EVAL, lazyValue); + } + + /** + * Initializes a LazyMetadataValue object with a specific cache strategy. + * + * @param owningPlugin the {@link Plugin} that created this metadata value. + * @param cacheStrategy determines the rules for caching this metadata value. + * @param lazyValue the lazy value assigned to this metadata value. + */ + public LazyMetadataValue(Plugin owningPlugin, CacheStrategy cacheStrategy, Callable<Object> lazyValue) { + Validate.notNull(owningPlugin, "owningPlugin cannot be null"); + Validate.notNull(cacheStrategy, "cacheStrategy cannot be null"); + Validate.notNull(lazyValue, "lazyValue cannot be null"); + + this.lazyValue = lazyValue; + this.owningPlugin = owningPlugin; + this.cacheStrategy = cacheStrategy; + } + + public Plugin getOwningPlugin() { + return owningPlugin; + } + + public Object value() { + eval(); + Object value = internalValue.get(); + if (value == ACTUALLY_NULL) { + return null; + } + return value; + } + + public int asInt() { + return NumberConversions.toInt(value()); + } + + public float asFloat() { + return NumberConversions.toFloat(value()); + } + + public double asDouble() { + return NumberConversions.toDouble(value()); + } + + public long asLong() { + return NumberConversions.toLong(value()); + } + + public short asShort() { + return NumberConversions.toShort(value()); + } + + public byte asByte() { + return NumberConversions.toByte(value()); + } + + public boolean asBoolean() { + Object value = value(); + if (value instanceof Boolean) { + return (Boolean) value; + } + + if (value instanceof Number) { + return ((Number) value).intValue() != 0; + } + + if (value instanceof String) { + return Boolean.parseBoolean((String) value); + } + + return value != null; + } + + public String asString() { + Object value = value(); + + if (value == null) { + return ""; + } + return value.toString(); + } + + /** + * Lazily evaluates the value of this metadata item. + * + * @throws MetadataEvaluationException if computing the metadata value fails. + */ + private synchronized void eval() throws MetadataEvaluationException { + if (cacheStrategy == CacheStrategy.NEVER_CACHE || internalValue.get() == null) { + try { + Object value = lazyValue.call(); + if (value == null) { + value = ACTUALLY_NULL; + } + internalValue = new SoftReference<Object>(value); + } catch (Exception e) { + throw new MetadataEvaluationException(e); + } + } + } + + public synchronized void invalidate() { + if (cacheStrategy != CacheStrategy.CACHE_ETERNALLY) { + internalValue.clear(); + } + } + + /** + * Describes possible caching strategies for metadata. + */ + public enum CacheStrategy { + /** + * Once the metadata value has been evaluated, do not re-evaluate the value until it is manually invalidated. + */ + CACHE_AFTER_FIRST_EVAL, + + /** + * Re-evaluate the metadata item every time it is requested + */ + NEVER_CACHE, + + /** + * Once the metadata value has been evaluated, do not re-evaluate the value in spite of manual invalidation. + */ + CACHE_ETERNALLY + } +} diff --git a/src/main/java/org/bukkit/metadata/MetadataConversionException.java b/src/main/java/org/bukkit/metadata/MetadataConversionException.java new file mode 100644 index 00000000..ff4d1205 --- /dev/null +++ b/src/main/java/org/bukkit/metadata/MetadataConversionException.java @@ -0,0 +1,13 @@ +package org.bukkit.metadata; + +/** + * A MetadataConversionException is thrown any time a {@link LazyMetadataValue} attempts to convert a metadata value + * to an inappropriate data type. + */ + +@SuppressWarnings("serial") +public class MetadataConversionException extends RuntimeException { + MetadataConversionException(String message) { + super(message); + } +} diff --git a/src/main/java/org/bukkit/metadata/MetadataEvaluationException.java b/src/main/java/org/bukkit/metadata/MetadataEvaluationException.java new file mode 100644 index 00000000..6b5ac886 --- /dev/null +++ b/src/main/java/org/bukkit/metadata/MetadataEvaluationException.java @@ -0,0 +1,13 @@ +package org.bukkit.metadata; + +/** + * A MetadataEvaluationException is thrown any time a {@link LazyMetadataValue} fails to evaluate its value due to + * an exception. The originating exception will be included as this exception's cause. + */ + +@SuppressWarnings("serial") +public class MetadataEvaluationException extends RuntimeException { + MetadataEvaluationException(Throwable cause) { + super(cause); + } +} diff --git a/src/main/java/org/bukkit/metadata/MetadataStore.java b/src/main/java/org/bukkit/metadata/MetadataStore.java new file mode 100644 index 00000000..0adfa7a0 --- /dev/null +++ b/src/main/java/org/bukkit/metadata/MetadataStore.java @@ -0,0 +1,52 @@ +package org.bukkit.metadata; + +import org.bukkit.plugin.Plugin; + +import java.util.List; + +public interface MetadataStore<T> { + /** + * Adds a metadata value to an object. + * + * @param subject The object receiving the metadata. + * @param metadataKey A unique key to identify this metadata. + * @param newMetadataValue The metadata value to apply. + */ + public void setMetadata(T subject, String metadataKey, MetadataValue newMetadataValue); + + /** + * Returns all metadata values attached to an object. If multiple plugins have attached metadata, each will value + * will be included. + * + * @param subject the object being interrogated. + * @param metadataKey the unique metadata key being sought. + * @return A list of values, one for each plugin that has set the requested value. + */ + public List<MetadataValue> getMetadata(T subject, String metadataKey); + + /** + * Tests to see if a metadata attribute has been set on an object. + * + * @param subject the object upon which the has-metadata test is performed. + * @param metadataKey the unique metadata key being queried. + * @return the existence of the metadataKey within subject. + */ + public boolean hasMetadata(T subject, String metadataKey); + + /** + * Removes a metadata item owned by a plugin from a subject. + * + * @param subject the object to remove the metadata from. + * @param metadataKey the unique metadata key identifying the metadata to remove. + * @param owningPlugin the plugin attempting to remove a metadata item. + */ + public void removeMetadata(T subject, String metadataKey, Plugin owningPlugin); + + /** + * Invalidates all metadata in the metadata store that originates from the given plugin. Doing this will force + * each invalidated metadata item to be recalculated the next time it is accessed. + * + * @param owningPlugin the plugin requesting the invalidation. + */ + public void invalidateAll(Plugin owningPlugin); +} diff --git a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java new file mode 100644 index 00000000..0c384abe --- /dev/null +++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java @@ -0,0 +1,143 @@ +package org.bukkit.metadata; + +import org.bukkit.plugin.Plugin; + +import java.util.*; + +public abstract class MetadataStoreBase<T> { + private Map<String, List<MetadataValue>> metadataMap = new HashMap<String, List<MetadataValue>>(); + private WeakHashMap<T, String> disambiguationCache = new WeakHashMap<T, String>(); + + /** + * Adds a metadata value to an object. Each metadata value is owned by a specific{@link Plugin}. + * If a plugin has already added a metadata value to an object, that value + * will be replaced with the value of {@code newMetadataValue}. Multiple plugins can set independent values for + * the same {@code metadataKey} without conflict. + * + * Implementation note: I considered using a {@link java.util.concurrent.locks.ReadWriteLock} for controlling + * access to {@code metadataMap}, but decided that the added overhead wasn't worth the finer grained access control. + * Bukkit is almost entirely single threaded so locking overhead shouldn't pose a problem. + * + * @see MetadataStore#setMetadata(Object, String, MetadataValue) + * @param subject The object receiving the metadata. + * @param metadataKey A unique key to identify this metadata. + * @param newMetadataValue The metadata value to apply. + */ + public synchronized void setMetadata(T subject, String metadataKey, MetadataValue newMetadataValue) { + String key = cachedDisambiguate(subject, metadataKey); + if (!metadataMap.containsKey(key)) { + metadataMap.put(key, new ArrayList<MetadataValue>()); + } + // we now have a list of subject's metadata for the given metadata key. If newMetadataValue's owningPlugin + // is found in this list, replace the value rather than add a new one. + List<MetadataValue> metadataList = metadataMap.get(key); + for (int i = 0; i < metadataList.size(); i++) { + if (metadataList.get(i).getOwningPlugin().equals(newMetadataValue.getOwningPlugin())) { + metadataList.set(i, newMetadataValue); + return; + } + } + // we didn't find a duplicate...add the new metadata value + metadataList.add(newMetadataValue); + } + + /** + * Returns all metadata values attached to an object. If multiple plugins have attached metadata, each will value + * will be included. + * + * @see MetadataStore#getMetadata(Object, String) + * @param subject the object being interrogated. + * @param metadataKey the unique metadata key being sought. + * @return A list of values, one for each plugin that has set the requested value. + */ + public synchronized List<MetadataValue> getMetadata(T subject, String metadataKey) { + String key = cachedDisambiguate(subject, metadataKey); + if (metadataMap.containsKey(key)) { + return Collections.unmodifiableList(metadataMap.get(key)); + } else { + return Collections.emptyList(); + } + } + + /** + * Tests to see if a metadata attribute has been set on an object. + * + * @param subject the object upon which the has-metadata test is performed. + * @param metadataKey the unique metadata key being queried. + * @return the existence of the metadataKey within subject. + */ + public synchronized boolean hasMetadata(T subject, String metadataKey) { + String key = cachedDisambiguate(subject, metadataKey); + return metadataMap.containsKey(key); + } + + /** + * Removes a metadata item owned by a plugin from a subject. + * + * @see MetadataStore#removeMetadata(Object, String, org.bukkit.plugin.Plugin) + * @param subject the object to remove the metadata from. + * @param metadataKey the unique metadata key identifying the metadata to remove. + * @param owningPlugin the plugin attempting to remove a metadata item. + */ + public synchronized void removeMetadata(T subject, String metadataKey, Plugin owningPlugin) { + String key = cachedDisambiguate(subject, metadataKey); + List<MetadataValue> metadataList = metadataMap.get(key); + for (int i = 0; i < metadataList.size(); i++) { + if (metadataList.get(i).getOwningPlugin().equals(owningPlugin)) { + metadataList.remove(i); + } + } + } + + /** + * Invalidates all metadata in the metadata store that originates from the given plugin. Doing this will force + * each invalidated metadata item to be recalculated the next time it is accessed. + * + * @see MetadataStore#invalidateAll(org.bukkit.plugin.Plugin) + * @param owningPlugin the plugin requesting the invalidation. + */ + public synchronized void invalidateAll(Plugin owningPlugin) { + if(owningPlugin == null) { + throw new IllegalArgumentException("owningPlugin cannot be null"); + } + + for (List<MetadataValue> values : metadataMap.values()) { + for (MetadataValue value : values) { + if (value.getOwningPlugin().equals(owningPlugin)) { + value.invalidate(); + } + } + } + } + + /** + * Caches the results of calls to {@link MetadataStoreBase#disambiguate(Object, String)} in a {@link WeakHashMap}. Doing so maintains a + * <a href="http://www.codeinstructions.com/2008/09/weakhashmap-is-not-cache-understanding.html">canonical list</a> + * of disambiguation strings for objects in memory. When those objects are garbage collected, the disambiguation string + * in the list is aggressively garbage collected as well. + * @param subject The object for which this key is being generated. + * @param metadataKey The name identifying the metadata value. + * @return a unique metadata key for the given subject. + */ + private String cachedDisambiguate(T subject, String metadataKey) { + if (disambiguationCache.containsKey(subject)) { + return disambiguationCache.get(subject); + } else { + String disambiguation = disambiguate(subject, metadataKey); + disambiguationCache.put(subject, disambiguation); + return disambiguation; + } + } + + /** + * Creates a unique name for the object receiving metadata by combining unique data from the subject with a metadataKey. + * The name created must be globally unique for the given object and any two equivalent objects must generate the + * same unique name. For example, two Player objects must generate the same string if they represent the same player, + * even if the objects would fail a reference equality test. + * + * @param subject The object for which this key is being generated. + * @param metadataKey The name identifying the metadata value. + * @return a unique metadata key for the given subject. + */ + protected abstract String disambiguate(T subject, String metadataKey); +} diff --git a/src/main/java/org/bukkit/metadata/MetadataValue.java b/src/main/java/org/bukkit/metadata/MetadataValue.java new file mode 100644 index 00000000..761d1ac9 --- /dev/null +++ b/src/main/java/org/bukkit/metadata/MetadataValue.java @@ -0,0 +1,73 @@ +package org.bukkit.metadata; + +import org.bukkit.plugin.Plugin; + +public interface MetadataValue { + + /** + * Fetches the value of this metadata item. + * + * @return the metadata value. + */ + public Object value(); + + /** + * Attempts to convert the value of this metadata item into an int. + * @return the value as an int. + */ + public int asInt(); + + /** + * Attempts to convert the value of this metadata item into a float. + * @return the value as a float. + */ + public float asFloat(); + + /** + * Attempts to convert the value of this metadata item into a double. + * @return the value as a double. + */ + public double asDouble(); + + /** + * Attempts to convert the value of this metadata item into a long. + * @return the value as a long. + */ + public long asLong(); + + /** + * Attempts to convert the value of this metadata item into a short. + * @return the value as a short. + */ + public short asShort(); + + /** + * Attempts to convert the value of this metadata item into a byte. + * @return the value as a byte. + */ + public byte asByte(); + + /** + * Attempts to convert the value of this metadata item into a boolean. + * @return the value as a boolean. + */ + public boolean asBoolean(); + + /** + * Attempts to convert the value of this metadata item into a string. + * @return the value as a string. + */ + public String asString(); + + /** + * Returns the {@link Plugin} that created this metadata item. + * + * @return the plugin that owns this metadata value. + */ + public Plugin getOwningPlugin(); + + /** + * Invalidates this metadata item, forcing it to recompute when next accessed. + */ + public void invalidate(); +} diff --git a/src/main/java/org/bukkit/metadata/Metadatable.java b/src/main/java/org/bukkit/metadata/Metadatable.java new file mode 100644 index 00000000..956a1960 --- /dev/null +++ b/src/main/java/org/bukkit/metadata/Metadatable.java @@ -0,0 +1,42 @@ +package org.bukkit.metadata; + +import org.bukkit.plugin.Plugin; + +import java.util.List; + +/** + * This interface is implemented by all objects that can provide metadata about themselves. + */ +public interface Metadatable { + /** + * Sets a metadata value in the implementing object's metadata store. + * + * @param metadataKey A unique key to identify this metadata. + * @param newMetadataValue The metadata value to apply. + */ + public void setMetadata(String metadataKey, MetadataValue newMetadataValue); + + /** + * Returns a list of previously set metadata values from the implementing object's metadata store. + * + * @param metadataKey the unique metadata key being sought. + * @return A list of values, one for each plugin that has set the requested value. + */ + public List<MetadataValue> getMetadata(String metadataKey); + + /** + * Tests to see whether the implementing object contains the given metadata value in its metadata store. + * + * @param metadataKey the unique metadata key being queried. + * @return the existence of the metadataKey within subject. + */ + public boolean hasMetadata(String metadataKey); + + /** + * Removes the given metadata value from the implementing object's metadata store. + * + * @param metadataKey the unique metadata key identifying the metadata to remove. + * @param owningPlugin This plugin's metadata value will be removed. All other values will be left untouched. + */ + public void removeMetadata(String metadataKey, Plugin owningPlugin); +} diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java index 450252d8..97c882aa 100644 --- a/src/main/java/org/bukkit/plugin/Plugin.java +++ b/src/main/java/org/bukkit/plugin/Plugin.java @@ -14,22 +14,21 @@ import com.avaje.ebean.EbeanServer; /** * Represents a Plugin */ -public interface Plugin extends CommandExecutor { - +public abstract class Plugin implements CommandExecutor { /** * Returns the folder that the plugin data's files are located in. The * folder may not yet exist. * * @return The folder */ - public File getDataFolder(); + public abstract File getDataFolder(); /** * Returns the plugin.yaml file containing the details for this plugin * * @return Contents of the plugin.yaml file */ - public PluginDescriptionFile getDescription(); + public abstract PluginDescriptionFile getDescription(); /** * Gets a {@link FileConfiguration} for this plugin, read through "config.yml" @@ -39,7 +38,7 @@ public interface Plugin extends CommandExecutor { * * @return Plugin configuration */ - public FileConfiguration getConfig(); + public abstract FileConfiguration getConfig(); /** * Gets an embedded resource in this plugin @@ -47,18 +46,18 @@ public interface Plugin extends CommandExecutor { * @param filename Filename of the resource * @return File if found, otherwise null */ - public InputStream getResource(String filename); + public abstract InputStream getResource(String filename); /** * Saves the {@link FileConfiguration} retrievable by {@link #getConfig()}. */ - public void saveConfig(); + public abstract void saveConfig(); /** * Saves the raw contents of the default config.yml file to the location retrievable by {@link #getConfig()}. * If there is no default config.yml embedded in the plugin, an empty config.yml file is saved. */ - public void saveDefaultConfig(); + public abstract void saveDefaultConfig(); /** * Saves the raw contents of any resource embedded with a plugin's .jar file assuming it can be found using @@ -69,70 +68,70 @@ public interface Plugin extends CommandExecutor { * @param replace if true, the embedded resource will overwrite the contents of an existing file. * @throws IllegalArgumentException if the resource path is null, empty, or points to a nonexistent resource. */ - public void saveResource(String resourcePath, boolean replace); + public abstract void saveResource(String resourcePath, boolean replace); /** * Discards any data in {@link #getConfig()} and reloads from disk. */ - public void reloadConfig(); + public abstract void reloadConfig(); /** * Gets the associated PluginLoader responsible for this plugin * * @return PluginLoader that controls this plugin */ - public PluginLoader getPluginLoader(); + public abstract PluginLoader getPluginLoader(); /** * Returns the Server instance currently running this plugin * * @return Server running this plugin */ - public Server getServer(); + public abstract Server getServer(); /** * Returns a value indicating whether or not this plugin is currently enabled * * @return true if this plugin is enabled, otherwise false */ - public boolean isEnabled(); + public abstract boolean isEnabled(); /** * Called when this plugin is disabled */ - public void onDisable(); + public abstract void onDisable(); /** * Called after a plugin is loaded but before it has been enabled. * When mulitple plugins are loaded, the onLoad() for all plugins is called before any onEnable() is called. */ - public void onLoad(); + public abstract void onLoad(); /** * Called when this plugin is enabled */ - public void onEnable(); + public abstract void onEnable(); /** * Simple boolean if we can still nag to the logs about things * * @return boolean whether we can nag */ - public boolean isNaggable(); + public abstract boolean isNaggable(); /** * Set naggable state * * @param canNag is this plugin still naggable? */ - public void setNaggable(boolean canNag); + public abstract void setNaggable(boolean canNag); /** * Gets the {@link EbeanServer} tied to this plugin * * @return Ebean server instance */ - public EbeanServer getDatabase(); + public abstract EbeanServer getDatabase(); /** * Gets a {@link ChunkGenerator} for use in a default world, as specified in the server configuration @@ -141,7 +140,7 @@ public interface Plugin extends CommandExecutor { * @param id Unique ID, if any, that was specified to indicate which generator was requested * @return ChunkGenerator for use in the default world generation */ - public ChunkGenerator getDefaultWorldGenerator(String worldName, String id); + public abstract ChunkGenerator getDefaultWorldGenerator(String worldName, String id); /** * Returns the primary logger associated with this server instance. The returned logger automatically @@ -149,5 +148,35 @@ public interface Plugin extends CommandExecutor { * * @return Logger associated with this server */ - public Logger getLogger(); + public abstract Logger getLogger(); + + /** + * Returns the name of the plugin. + * + * This should return the bare name of the plugin and should be used for comparison. + * + * @return name of the plugin + */ + public String getName() { + return getDescription().getName(); + } + + @Override + public int hashCode() { + return getName().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof Plugin)) { + return false; + } + return getName().equals(((Plugin) obj).getName()); + } } diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java index 10b19e91..6cc7d9db 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java @@ -34,7 +34,7 @@ import com.avaje.ebeaninternal.server.ddl.DdlGenerator; /** * Represents a Java plugin */ -public abstract class JavaPlugin implements Plugin { +public abstract class JavaPlugin extends Plugin { private boolean isEnabled = false; private boolean initialized = false; private PluginLoader loader = null; diff --git a/src/main/java/org/bukkit/util/NumberConversions.java b/src/main/java/org/bukkit/util/NumberConversions.java index f70cc314..9c0b132f 100644 --- a/src/main/java/org/bukkit/util/NumberConversions.java +++ b/src/main/java/org/bukkit/util/NumberConversions.java @@ -9,84 +9,78 @@ public final class NumberConversions { public static int toInt(Object object) { if (object instanceof Number) { return ((Number) object).intValue(); - } else { - int result = 0; - - try { - result = Integer.parseInt(object.toString()); - } catch (NumberFormatException ex) {} + } - return result; + try { + return Integer.valueOf(object.toString()); + } catch (NumberFormatException e) { + } catch (NullPointerException e) { } + return 0; } public static float toFloat(Object object) { if (object instanceof Number) { return ((Number) object).floatValue(); - } else { - float result = 0; - - try { - result = Float.parseFloat(object.toString()); - } catch (NumberFormatException ex) {} + } - return result; + try { + return Float.valueOf(object.toString()); + } catch (NumberFormatException e) { + } catch (NullPointerException e) { } + return 0; } public static double toDouble(Object object) { if (object instanceof Number) { return ((Number) object).doubleValue(); - } else { - double result = 0; - - try { - result = Double.parseDouble(object.toString()); - } catch (NumberFormatException ex) {} + } - return result; + try { + return Double.valueOf(object.toString()); + } catch (NumberFormatException e) { + } catch (NullPointerException e) { } + return 0; } public static long toLong(Object object) { if (object instanceof Number) { return ((Number) object).longValue(); - } else { - long result = 0; - - try { - result = Long.parseLong(object.toString()); - } catch (NumberFormatException ex) {} + } - return result; + try { + return Long.valueOf(object.toString()); + } catch (NumberFormatException e) { + } catch (NullPointerException e) { } + return 0; } public static short toShort(Object object) { if (object instanceof Number) { return ((Number) object).shortValue(); - } else { - short result = 0; - - try { - result = Short.parseShort(object.toString()); - } catch (NumberFormatException ex) {} + } - return result; + try { + return Short.valueOf(object.toString()); + } catch (NumberFormatException e) { + } catch (NullPointerException e) { } + return 0; } public static byte toByte(Object object) { if (object instanceof Number) { return ((Number) object).byteValue(); - } else { - byte result = 0; - - try { - result = Byte.parseByte(object.toString()); - } catch (NumberFormatException ex) {} + } - return result; + try { + return Byte.valueOf(object.toString()); + } catch (NumberFormatException e) { + } catch (NullPointerException e) { } + return 0; } } |