Extensions
Extensions allow one plugin to add data fields to another plugin's database entries without modifying the original entry class. This is how Spark maintains modularity while letting plugins work together.
When to Use Extensions
Use extensions when your plugin needs to store data on entries that belong to another plugin. Common examples:
Combat plugin storing stat values on item entries
Crafting plugin storing recipe unlock data on profession entries
Progression plugin storing experience rewards on quest entries
If you control both the entry and the data, just add fields directly to the entry. Extensions are for cross-plugin scenarios.
How Extensions Work
An extension consists of three parts:
Extension Data: A ScriptableObject that holds the extra fields, linked to a target entry by ID.
Extension Manifest: A configuration asset that tells the Spark Editor where and how to display the extension.
Extension Logic (optional): Event handlers or other code that uses the extension data.
At runtime, extension data is loaded by SparkExtensionRegistry and accessed by combining the extension type and target entry ID.
Creating Extension Data
Inherit from SparkDatabaseExtensionData:
SparkDatabaseExtensionData inherits from ScriptableObject and has a targetId field that stores the ID of the database entry it extends. This is managed automatically by the Spark Editor.
Storage
Extension data files are stored alongside the plugin that creates them, in a Resources/ subfolder:
Accessing Extension Data at Runtime
Use SparkExtensionRegistry:
The registry uses a cache key format of {ExtensionType}|{TargetId} for O(1) lookups.
IPluginExtension Interface
To make your extension appear in the Spark Editor, implement IPluginExtension:
Properties:
TargetType
The entry type this extension applies to (e.g., typeof(CharacterEntry)).
Priority
Display order in the editor. Higher values appear earlier.
ExtensionDisplayName
Label shown in the Spark Editor.
IsCollapsible
Whether the extension section can be collapsed.
IGlobalPluginExtension
If your extension should apply to multiple entry types, implement IGlobalPluginExtension instead:
The framework wraps each supported type in a GlobalExtensionWrapper for editor rendering.
Extension Manifest
Create a PluginExtensionManifest ScriptableObject to configure how the extension appears:
Right-click in your extension's Editor folder.
Create a
PluginExtensionManifestasset.Configure it with the extension data type, target type, and resource path.
The manifest tells the Spark Editor where to find and create extension data assets.
Extension Folder Structure
The standard folder layout for an extension:
The assembly definition for the extension references both the source plugin and the target plugin's assemblies.
Null Safety
Always guard extension data lookups. The target plugin may be installed but the extension data may not exist for every entry:
This is especially important for optional plugins. If the extension plugin is not installed, the lookup simply returns null.
Best Practices
Name extensions clearly:
{Feature}{TargetPlugin}Extension(e.g.,CombatStatsItemExtension).Keep extension data focused. One extension per concern.
Use
ShouldShowForTarget()to filter which entries actually need the extension fields.Always null-check extension data at runtime.
Store extension data under your plugin's folder, not the target plugin's folder.
Add assembly references only to the plugins you actually need.
Last updated
Was this helpful?
