Data Adapter
Overview
Dill Pixel provides a robust data management system through its DataAdapter class. This system allows you to:
- Store and retrieve game data
- increment numeric values
- append strings
- concatenate arrays
- deep merge data
- Persist data to localStorage
- Listen for data changes
- Selectively backup specific data keys
Basic Configuration
Configure data management in your dill-pixel.config.ts
:
export type Data = { score: number; playerName: string; settings: { soundEnabled: boolean; musicVolume: number; };};export const config = defineConfig<Data>({ // ... other config options data: { // Initial data values initial: { score: 0, playerName: '', settings: { soundEnabled: true, musicVolume: 0.5, }, }, // Keys to backup to localStorage backupKeys: ['settings'], // Whether to backup all data (alternative to specifying keys) backupAll: false, // Optional namespace for localStorage keys namespace: 'my-game', },});
Data Manipulation Methods
The DataAdapter provides several methods for managing game data. Each has specific use cases and behaviors.
set() Method
The set()
method allows updating single or multiple values, with optional deep merging:
// Update a single valuethis.app.data.set('score', 100);
// Update multiple values with deep merge (default)this.app.data.set({ score: 100, settings: { soundEnabled: false, // Only updates soundEnabled, preserves other settings },});
this.app.data.set('score', 'pickle'); // will throw a ts error
Deep Merge Behavior
You can also use the merge
parameter to control the merge behavior. By default, the set()
method will merge the new data with the existing data, passing false
will replace the entire data object.
// Initial data, set in dill-pixel.config.tsdefineConfig<Data>({ // ... other config options data: { initial: { settings: { sound: { enabled: true, volume: 0.5 }, display: { fullscreen: false }, }, }, },});
// Update with deep mergethis.app.data.set({ settings: { sound: { volume: 0.8 } }});
/* Result: { settings: { sound: { enabled: true, volume: 0.8 }, display: { fullscreen: false } } } */
// Replace entire data object (no merge)this.app.data.set( { score: 0, settings: { soundEnabled: true, musicVolume: 1.0, }, }, false, // do not merge);
get() Method
The get()
method retrieves data from storage:
// Get entire data objectconst allData = this.app.data.get();
// Get specific fieldconst score = this.app.data.get('score');const settings = this.app.data.get('settings');
clear() Method
The clear()
method removes data both from memory and localStorage:
// Clear all datathis.app.data.clear();
// Clear specific fieldthis.app.data.clear('score');
increment() Method
The increment()
method provides a type-safe way to increment numeric values:
// Set initial value (could also be set in dill-pixel.config.ts)this.app.data.set('score', 0);
// Increment by 1 (default)this.app.data.increment('score'); // score is now 1
// Increment by specific amountthis.app.data.increment('score', 10); // score is now 11
// property value must be defined as a numberthis.app.data.increment('someStringValueKey', 10); // will throw a ts error
concat() Method
The concat()
method allows you to append values to array properties:
// E.G. the `inventory` property has previously been defined as an array of strings
// Initialize empty arraythis.app.data.set('inventory', ['sword']);// Add single itemthis.app.data.concat('inventory', 'shield');// Add multiple itemsthis.app.data.concat('inventory', ['potion', 'book']);// Result: inventory = ['sword', 'shield', 'potion', 'book']
// property value must be defined as an arraythis.app.data.concat('inventory', [1, 2, 3]); // will throw a ts error
append() Method
The append()
method is used to concatenate strings with optional separators:
// E.G. the `stuff` property has previously been defined as a string
// set the initial valuethis.app.data.set('stuff', 'things');// Append a single stringthis.app.data.append('stuff', 'more', '-');// Result: stuff = 'things-more'
// set the initial valuethis.app.data.set('stuff2', 'things');// Append multiple strings, uses the ' ' separatorthis.app.data.append('stuff2', ['more', 'stuff'], ' ');// Result: stuff2 = 'things more stuff'
snapshot() Method
The snapshot()
method creates a deep copy of your game data, useful for:
- Creating save states
- Comparing data changes
- Debugging
- Implementing undo/redo functionality
// Get snapshot of all dataconst fullSnapshot = this.app.data.snapshot();
// Get snapshot of specific fieldconst scoreSnapshot = this.app.data.snapshot('score');
Example Use Cases
// Create a save pointconst savePoint = this.app.data.snapshot();
// Later, restore the save pointthis.app.data.set(savePoint, false); // false = don't merge
// Log data at specific points without worrying about reference issuesconsole.log('Game state before battle:', this.app.data.snapshot());startBattle();console.log('Game state after battle:', this.app.data.snapshot());
Change Signal
All data modifications emit change events that you can listen to:
this.app.data.onDataChange.add((detail) => { const { key, value, restore } = detail;
// Single key updates (from save()) if (typeof key === 'string') { console.log(`${key} updated to:`, value); }
// Multiple key updates (from set()) if (Array.isArray(key)) { console.log('Updated keys:', key); }
// Restoration from localStorage if (restore) { console.log('Data restored from localStorage'); }});