Skip to content

Data Adapter

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

Configure data management in your dill-pixel.config.ts. The framework uses a defineData helper to ensure your data is fully type-safe.

import { defineConfig, defineData } from 'dill-pixel';
// 1. Define your data schema
export const dataSchema = defineData({
score: 0,
playerName: '',
settings: {
soundEnabled: true,
musicVolume: 0.5,
},
});
// 2. Add it to your main config
export default defineConfig({
// ... other config options
data: {
// Initial data values can override the schema defaults
initial: {
playerName: 'Hero',
},
// 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',
},
});

The DataAdapter provides several methods for managing game data. Each has specific use cases and behaviors.

The set() method allows updating single or multiple values, with optional deep merging:

// Update a single value
this.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

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.

import { defineConfig, defineData } from 'dill-pixel';
export const dataSchema = defineData({
settings: {
sound: { enabled: true, volume: 0.5 },
display: { fullscreen: false },
},
});
// Initial data is now part of the main config
export default defineConfig({
data: {
initial: {
settings: {
sound: { enabled: true, volume: 0.5 },
display: { fullscreen: false },
},
},
},
});
// This example would fail with type-safety unless you provide all fields!
// It's generally safer to use deep merging.
this.app.data.set(
{
score: 0,
playerName: 'New Player',
settings: {
soundEnabled: true,
musicVolume: 1.0,
},
},
false, // do not merge
);

The get() method retrieves data from storage:

// Get entire data object
const allData = this.app.data.get();
// Get specific field
const score = this.app.data.get('score');
const settings = this.app.data.get('settings');

The clear() method removes data both from memory and localStorage:

// Clear all data
this.app.data.clear();
// Clear specific field
this.app.data.clear('score');

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 amount
this.app.data.increment('score', 10); // score is now 11
// property value must be defined as a number
this.app.data.increment('someStringValueKey', 10); // will throw a ts error

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 array
this.app.data.set('inventory', ['sword']);
// Add single item
this.app.data.concat('inventory', 'shield');
// Add multiple items
this.app.data.concat('inventory', ['potion', 'book']);
// Result: inventory = ['sword', 'shield', 'potion', 'book']
// property value must be defined as an array
this.app.data.concat('inventory', [1, 2, 3]); // will throw a ts error

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 value
this.app.data.set('stuff', 'things');
// Append a single string
this.app.data.append('stuff', 'more', '-');
// Result: stuff = 'things-more'
// set the initial value
this.app.data.set('stuff2', 'things');
// Append multiple strings, uses the ' ' separator
this.app.data.append('stuff2', ['more', 'stuff'], ' ');
// Result: stuff2 = 'things more stuff'

The snapshot() method returns a deep copy of the data at a specific point in time, which is useful for debugging or comparing states.

// Log data at specific points without worrying about reference issues
console.log('Game state before battle:', this.app.data.snapshot());
startBattle();
console.log('Game state after battle:', this.app.data.snapshot());

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');
}
});