[Bleeding] Added a Metadata framework for Entities, Blocks, and Worlds

This metadata implementation has the following features:

- All metadata is lazy. Metadata values are not actually computed until another plugin requests them. Memory and CPU are conserved by not computing and storing unnecessary metadata values.

- All metadata is cached. Once a metadata value is computed its value is cached in the metadata store to prevent further unnecessary computation. An invalidation mechanism is provided to flush the cache and force recompilation of metadata values.

- All metadata is stored in basic data types. Convenience methods in the MetadataValue class allow for the conversion of metadata data types when possible. Restricting metadata to basic data types prevents the accidental linking of large object graphs into metadata. Metadata is persistent across the lifetime of the application and adding large object graphs would damage garbage collector performance.

- Metadata access is thread safe. Care has been taken to protect the internal data structures and access them in a thread safe manner.

- Metadata is exposed for all objects that descend from Entity, Block, and World. All Entity and World metadata is stored at the Server  level and all Block metadata is stored at the World level.

- Metadata is NOT keyed on references to original objects - instead metadata is keyed off of unique fields within those objects. Doing this allows metadata to exist for blocks that are in chunks not currently in memory. Additionally, Player objects are keyed off of player name so that Player metadata remains consistent between logins.

- Metadata convenience methods have been added to all Entities, Players, Blocks, BlockStates, and World allowing direct access to an individual instance's metadata.

- Players and OfflinePlayers share a single metadata store, allowing player metadata to be manipulated regardless of the player's current online status.

By: rmichela <deltahat@gmail.com>
This commit is contained in:
Bukkit/Spigot
2011-12-08 00:33:33 -05:00
parent 5906da7948
commit dd1bee786b
22 changed files with 1064 additions and 78 deletions

View File

@@ -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());
}
}

View File

@@ -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;