Phaser 3 plugin for Hyve SDK integration
npm install @hyve-sdk/phaserhyve-access URL parameter
sendTelemetry method for all tracking needs
bash
npm install @hyve/phaser-plugin
or
pnpm add @hyve/phaser-plugin
`
$3
`html
`
Usage
$3
`javascript
import Phaser from 'phaser';
import HyvePhaserPlugin from '@hyve/phaser-plugin';
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
plugins: {
global: [{
key: 'HyvePhaserPlugin',
plugin: HyvePhaserPlugin,
start: true,
data: {
isDev: true, // Use dev environment (default: true)
debug: false // Enable debug logging (default: false)
}
}]
},
scene: [MainScene]
};
const game = new Phaser.Game(config);
`
$3
`javascript
class MainScene extends Phaser.Scene {
create() {
// Get plugin reference
const hyve = this.plugins.get('HyvePhaserPlugin');
// Check authentication
if (hyve.isAuthenticated()) {
console.log('User ID:', hyve.getUserId());
}
// Track game events using sendTelemetry
hyve.sendTelemetry(
'game', // event_location
'gameplay', // event_category
'start', // event_action
'my-game', // event_sub_category
null, // event_sub_action
{ // event_details (auto-validated and stringified)
version: '1.0.0',
platform: 'web'
}
);
// Track player actions
hyve.sendTelemetry(
'game',
'player',
'action',
'movement',
'jump',
{ level: 1, height: 100 }
);
}
onLevelComplete() {
const hyve = this.plugins.get('HyvePhaserPlugin');
hyve.sendTelemetry(
'game',
'level',
'complete',
'level_1',
null,
null,
{ score: 1000, time: 60 }
);
}
}
`
API Reference
$3
`typescript
interface HyvePhaserPluginConfig {
apiKey?: string; // API key for telemetry
isDev?: boolean; // Use dev environment (default: true)
debug?: boolean; // Enable debug logging (default: false)
storageMode?: 'cloud' | 'local'; // Storage mode for persistent game data (default: 'cloud')
}
`
#### Storage Modes
Choose between cloud or local storage per operation. Defaults to cloud.
| Mode | Syncs | Requires JWT | Offline | Use Case |
|------|-------|--------------|---------|----------|
| cloud (default) | ✅ Cross-device | ✅ Required | ❌ No | Progression, scores |
| local | ❌ Device-only | ❌ Not needed | ✅ Yes | Settings, preferences |
`javascript
// Specify storage per call (parameter: 'cloud' | 'local')
await hyve.saveGameData('level', 5, 'cloud'); // Syncs across devices
await hyve.saveGameData('volume', 0.8, 'local'); // Device-specific
await hyve.saveGameData('temp', 'x'); // Uses cloud (default)
// Set default in config (optional - already defaults to 'cloud')
data: { storageMode: 'local' } // All calls without param use local
`
$3
#### Authentication
- isAuthenticated(): boolean - Check if user is authenticated
- getUserId(): string | null - Get the authenticated user's ID
- getSessionId(): string - Get the current session ID
- hasJwtToken(): boolean - Check if JWT token is available
- getJwtToken(): string | null - Get the JWT token string
- authenticateFromUrl(): Promise - Manually trigger authentication
#### API Calls
Generic API Call:
`typescript
callApi(endpoint: string, options?: RequestInit): Promise
`
Make authenticated API requests to any endpoint:
`javascript
// GET request
const userData = await hyve.callApi('/api/v1/user');
// POST request
const result = await hyve.callApi('/api/v1/game/score', {
method: 'POST',
body: JSON.stringify({ score: 1000 })
});
`
Inventory Methods:
`typescript
// Get all inventory items
getInventory(): Promise
// Get specific inventory item by ID
getInventoryItem(itemId: string): Promise
`
Example usage:
`javascript
// Fetch user's inventory
const inventory = await hyve.getInventory();
console.log(User has ${inventory.total_count} items);
// Display items
inventory.items.forEach(item => {
console.log(${item.item_type}: ${item.quantity}x);
});
// Get specific item
const item = await hyve.getInventoryItem('item-id-123');
console.log(Item details:, item);
`
Requirements:
- JWT token must be available (via hyve-access URL parameter)
- User must be authenticated
Persistent Storage Methods:
All methods accept optional storage?: 'cloud' | 'local' parameter (defaults to cloud).
`typescript
saveGameData(key: string, value: any, storage?: 'cloud' | 'local'): Promise
getGameData(key: string, storage?: 'cloud' | 'local'): Promise
deleteGameData(key: string, storage?: 'cloud' | 'local'): Promise
batchSaveGameData(items: {key, value}[], storage?: 'cloud' | 'local'): Promise
getMultipleGameData(keys: string[], storage?: 'cloud' | 'local'): Promise
deleteMultipleGameData(keys: string[], storage?: 'cloud' | 'local'): Promise
`
Example - Mixed Storage Strategy:
`javascript
// Save progression to cloud (syncs across devices)
await hyve.saveGameData('level', 10, 'cloud');
await hyve.saveGameData('score', 5000, 'cloud');
// Save preferences locally (device-specific, offline-ready)
await hyve.saveGameData('graphics', 'high', 'local');
await hyve.saveGameData('volume', 0.8, 'local');
// Retrieve from different storage
const level = await hyve.getGameData('level', 'cloud');
const volume = await hyve.getGameData('volume', 'local');
// Batch operations
await hyve.batchSaveGameData([
{ key: 'level_1', value: 3 },
{ key: 'level_2', value: 2 }
], 'cloud');
`
Requirements:
- game-id URL parameter required for namespacing
- Cloud: Requires JWT token (hyve-access URL parameter)
- Local: No authentication needed, works offline
#### Telemetry Method
`typescript
sendTelemetry(
location: string, // Where the event occurred (required)
category: string, // Main category of event (required)
action: string, // Action taken (required)
subCategory?: string | null, // Sub-category (pass null if not needed)
subAction?: string | null, // Sub-action (pass null if not needed)
eventDetails?: Record | string | null, // Event details (auto-validated, pass null if not needed)
platformId?: string | null // Platform identifier (pass null if not needed)
): Promise
`
#### Telemetry Payload Structure
When sent to the backend, events have this structure:
`typescript
{
session_id: string, // Auto-generated session ID
hyve_user_id: string, // User's wallet address or 'anonymous'
game_id: string, // Game identifier (from URL)
event_location: string, // Where the event occurred
event_category: string, // Main category
event_action: string, // Action taken
event_sub_category: string | null, // Sub-category
event_sub_action: string | null, // Sub-action
event_details: string | null, // JSON stringified event details (auto-validated)
platform_id: string | null // Platform identifier
}
`
$3
The plugin emits the following Phaser events:
`javascript
import { HyveEvents } from '@hyve/phaser-plugin';
// Listen for authentication
game.events.on(HyveEvents.AUTHENTICATED, (event) => {
console.log('Auth success:', event.success);
console.log('User ID:', event.userId);
});
// Listen for telemetry events
game.events.on(HyveEvents.TELEMETRY_SENT, (event) => {
console.log('Telemetry sent:', event.eventName);
});
game.events.on(HyveEvents.TELEMETRY_ERROR, (event) => {
console.error('Telemetry error:', event.error);
});
// Listen for API call events
game.events.on(HyveEvents.API_CALL_SUCCESS, (event) => {
console.log('API success:', event.endpoint);
console.log('Response:', event.data);
});
game.events.on(HyveEvents.API_CALL_ERROR, (event) => {
console.error('API error:', event.endpoint, event.error);
});
// Plugin ready event
game.events.on(HyveEvents.PLUGIN_READY, (plugin) => {
console.log('Plugin is ready!');
});
`
Available Events:
- HyveEvents.AUTHENTICATED - Fired when authentication completes (success or failure)
- HyveEvents.TELEMETRY_SENT - Fired when telemetry is successfully sent
- HyveEvents.TELEMETRY_ERROR - Fired when telemetry fails to send
- HyveEvents.API_CALL_SUCCESS - Fired when an API call succeeds
- HyveEvents.API_CALL_ERROR - Fired when an API call fails
- HyveEvents.PLUGIN_READY - Fired when plugin is initialized
- HyveEvents.INSPECTOR_TOGGLED - Fired when inspector is toggled on/off
- HyveEvents.INSPECTOR_OBJECT_SELECTED - Fired when an object is selected
Complete Example: Using API & Inventory
`javascript
class GameScene extends Phaser.Scene {
async create() {
const hyve = this.plugins.get('HyvePhaserPlugin');
// Check authentication and JWT
if (!hyve.isAuthenticated() || !hyve.hasJwtToken()) {
console.error('User not authenticated or no JWT token');
return;
}
try {
// Fetch user's inventory
const inventory = await hyve.getInventory();
console.log(Player has ${inventory.total_count} items);
// Display inventory items in game
inventory.items.forEach((item, index) => {
this.add.text(10, 100 + (index * 30),
${item.item_type}: ${item.quantity}x,
{ fontSize: '16px', color: '#ffffff' }
);
});
// Track inventory view
await hyve.sendTelemetry(
'game', 'inventory', 'view', null, null,
{ item_count: inventory.total_count }
);
// Get details for first item
if (inventory.items.length > 0) {
const firstItem = inventory.items[0];
const itemDetails = await hyve.getInventoryItem(firstItem.id);
console.log('First item metadata:', itemDetails.metadata);
}
} catch (error) {
console.error('Failed to fetch inventory:', error);
}
}
async onItemUsed(itemId) {
const hyve = this.plugins.get('HyvePhaserPlugin');
// Get item details
const item = await hyve.getInventoryItem(itemId);
// Track item usage
await hyve.sendTelemetry(
'game', 'item', 'use', item.item_type, null,
{ item_id: itemId, quantity_before: item.quantity }
);
// Make API call to consume item
const result = await hyve.callApi('/api/v1/inventory/use', {
method: 'POST',
body: JSON.stringify({ item_id: itemId, quantity: 1 })
});
console.log('Item used:', result);
}
}
`
Common Telemetry Patterns
`javascript
// Game start
await hyve.sendTelemetry(
'game', 'gameplay', 'start', 'level_1', null,
{ mode: 'campaign', difficulty: 'normal' }
);
// Game end
await hyve.sendTelemetry(
'game', 'gameplay', 'end', null, null,
{ score: 1500, duration: 180, result: 'victory' }
);
// Level complete
await hyve.sendTelemetry(
'game', 'level', 'complete', 'level_3', null,
{ score: 2000, stars: 3, time: 120 }
);
// Achievement unlock
await hyve.sendTelemetry(
'game', 'achievement', 'unlock', 'first_win', null,
{ timestamp: Date.now(), rarity: 'common' }
);
// Player action
await hyve.sendTelemetry(
'game', 'player', 'action', 'power_up', 'speed_boost',
{ location: { x: 150, y: 200 }, duration: 10 }
);
`
Loading Methods
$3
`javascript
import HyvePhaserPlugin from '@hyve/phaser-plugin';
// Use in config as shown above
`
$3
`html
`
$3
`javascript
class PreloadScene extends Phaser.Scene {
preload() {
this.load.plugin('HyvePhaserPlugin',
'path/to/hyve-phaser-plugin.js',
true);
}
}
`
Environment Variables
For security, store your API key in environment variables:
`bash
.env.local
NEXT_PUBLIC_HYVE_API_KEY=your-api-key-here
`
`javascript
// In your game config
data: {
apiKey: process.env.NEXT_PUBLIC_HYVE_API_KEY,
isDev: process.env.NODE_ENV !== 'production'
}
`
TypeScript
Full TypeScript support is included. Types are automatically available when installed via NPM.
`typescript
import HyvePhaserPlugin, {
HyveEvents,
HyvePhaserPluginConfig,
HyveAuthEvent,
HyveTelemetryEvent,
HyveApiEvent,
InspectorObjectData,
InspectorConfig
} from '@hyve/phaser-plugin';
// Import types from the SDK
import type { Inventory, InventoryItem } from '@hyve-sdk/js';
`
Migration from v0.x
$3
- autoAuth config option - Plugin now always auto-authenticates
- Preconfigured telemetry methods - trackGameStart, trackGameEnd, etc. have been removed
- custom_data wrapper - Additional data is now directly JSON stringified into event_details
$3
Before (v0.x):
`javascript
// Old API
hyve.trackGameStart('my-game', { custom_data: { level: 1 } });
hyve.trackCustomEvent('player_action', { custom_data: { action: 'jump' } });
`
After (v1.x):
`javascript
// New unified API
hyve.sendTelemetry('game', 'gameplay', 'start', 'my-game', null, { level: 1 });
hyve.sendTelemetry('game', 'player', 'action', 'movement', 'jump', { height: 100 });
`
Game Object Inspector
The plugin includes a built-in inspector for debugging and visualizing game objects. This is particularly useful for:
- Building game editors
- QA and debugging
- Admin dashboards
- Analytics and tracking
$3
`javascript
// Toggle inspector on/off
window.dispatchEvent(new Event('hyve:toggleInspector'));
// Listen for object selections in parent window
window.addEventListener('message', (event) => {
if (event.data.type === 'hyve:inspector:selected') {
console.log('Selected object:', event.data.data);
}
});
`
$3
- Game Pause: Automatically pauses all active scenes when inspector is enabled
- High Visibility Borders: Bright yellow border with dark outline appears on hover
- Extended Data: Get position, scale, rotation, alpha, size, physics, textures with paths, and more
- Console Logging: Selections automatically logged to console
- Parent Communication: Send object data via postMessage
- Scene Support: Works across scene transitions
$3
`typescript
{
// Basic Info
type: string; // "Sprite", "Text", "Graphics", etc.
name: string; // Object name
// Transform
position: { x, y }; // World position
size: { width, height }; // Bounds dimensions
displaySize?: { width, height }; // Actual rendered size
scale: { x, y }; // Scale values
rotation: number; // Rotation in degrees
origin?: { x, y }; // Pivot point (0-1)
// Display
alpha: number; // Transparency (0-1)
visible: boolean; // Visibility state
active: boolean; // Active state
depth: number; // Z-index
tint?: number; // Color tint
// Asset/Texture (with file path!)
texture?: {
key: string; // Texture key
frame?: string; // Frame name
source?: string; // Actual file path/URL
};
// Text
text?: string; // Text content
textStyle?: {
fontFamily?: string;
fontSize?: string;
color?: string;
};
// Behavior
interactive?: boolean; // Has input enabled
scrollFactor?: { x, y }; // Parallax factor
// Hierarchy
container?: {
childrenCount: number; // Number of children
};
// Physics
physics?: {
velocity?: { x, y };
acceleration?: { x, y };
angularVelocity?: number;
immovable?: boolean;
};
}
`
$3
For complete integration guide with React/vanilla JS examples, see:
Inspector Documentation
Development
`bash
Install dependencies
pnpm install
Build the plugin
pnpm build
Watch mode for development
pnpm dev
``