Skip to main content

Hyve Phaser Plugin

The Hyve Phaser Plugin is a powerful integration tool that seamlessly connects Phaser 3 games with the Hyve platform, providing automatic authentication and telemetry tracking capabilities.

Installation

NPM Package

npm install @hyve-sdk/phaser
# or
pnpm add @hyve-sdk/phaser
# or
yarn add @hyve-sdk/phaser

Using the Game Template

The easiest way to get started is using the create-hyve-game template:

pnpm create hyve-game my-game
cd my-game
pnpm install

# Set up environment variables
cp .env.example .env.local
# Edit .env.local and add your Hyve API key

pnpm dev

Game Setup

Adding the Plugin to Your Phaser Game

Here's how to integrate the Hyve Phaser Plugin into your game configuration:

import { AUTO, Game } from "phaser";
import HyvePhaserPlugin from "@hyve-sdk/phaser";
import { MainScene } from "./scenes/MainScene";

// Game configuration
const config: Phaser.Types.Core.GameConfig = {
type: AUTO,
width: 800,
height: 600,
parent: "game-container",
backgroundColor: "#1a1a2e",
physics: {
default: "arcade",
arcade: {
gravity: { x: 0, y: 0 },
debug: false
}
},
plugins: {
global: [{
key: "HyvePhaserPlugin",
plugin: HyvePhaserPlugin,
start: true,
data: {
apiKey: process.env.NEXT_PUBLIC_HYVE_API_KEY || "",
isDev: true,
debug: true
}
}]
},
scene: [MainScene]
};

const StartGame = (parent: string) => {
return new Game({ ...config, parent });
};

export default StartGame;

JavaScript Version

import { AUTO, Game } from "phaser";
import HyvePhaserPlugin from "@hyve-sdk/phaser";
import { MainScene } from "./scenes/MainScene";

// Game configuration
const config = {
type: AUTO,
width: 800,
height: 600,
parent: "game-container",
backgroundColor: "#1a1a2e",
physics: {
default: "arcade",
arcade: {
gravity: { x: 0, y: 0 },
debug: false
}
},
plugins: {
global: [{
key: "HyvePhaserPlugin",
plugin: HyvePhaserPlugin,
start: true,
data: {
apiKey: process.env.NEXT_PUBLIC_HYVE_API_KEY || "",
isDev: true,
debug: false
}
}]
},
scene: [MainScene]
};

const StartGame = (parent) => {
return new Game({ ...config, parent });
};

export default StartGame;

Configuration

Plugin Configuration Options

OptionTypeDefaultDescription
apiKeystring''Your Hyve API key for telemetry (required for sending events)
isDevbooleantrueUse development environment (dev.hyve.gg vs prod.hyve.gg)
debugbooleanfalseEnable debug logging to console

Environment Variables

Create a .env.local file from the provided template:

# Copy the example file
cp .env.example .env.local

# Edit .env.local and add your API key
NEXT_PUBLIC_HYVE_API_KEY=your-actual-api-key

The .env.example file is included in the template as a reference for required environment variables.

// Use in configuration
data: {
apiKey: process.env.NEXT_PUBLIC_HYVE_API_KEY,
isDev: process.env.NODE_ENV !== 'production'
}

Authentication

How It Works

The plugin automatically authenticates users from URL parameters on initialization. No manual handling required!

Supported URL Formats

https://yourgame.com?hyve-token=signature.address.randomBase64.timestamp

Legacy Format

https://yourgame.com?signature=0x...&message=encoded_message

Manual Authentication

If you need to trigger authentication manually:

const hyve = this.plugins.get('HyvePhaserPlugin');

// Authenticate from current URL
await hyve.authenticateFromUrl();

Checking Authentication Status

const hyve = this.plugins.get('HyvePhaserPlugin');

if (hyve.isAuthenticated()) {
const userId = hyve.getUserId();
const sessionId = hyve.getSessionId();

console.log(`User ${userId} is authenticated`);
}

Telemetry Tracking

Using sendTelemetry

The plugin provides a single, flexible sendTelemetry method for all tracking needs. All optional parameters accept null to indicate no value:

const hyve = this.plugins.get('HyvePhaserPlugin');

// Basic telemetry
await hyve.sendTelemetry(
'game', // event_location (required)
'player', // event_category (required)
'jump', // event_action (required)
null, // event_sub_category (pass null if not needed)
null, // event_sub_action (pass null if not needed)
null, // event_details (pass null if not needed)
null // additionalData (pass null if not needed)
);

// With all parameters
await hyve.sendTelemetry(
'game', // event_location
'player', // event_category
'jump', // event_action
'double_jump', // event_sub_category
'successful', // event_sub_action
null, // event_details (will be JSON stringified additionalData)
{ // additionalData - becomes JSON in event_details
height: 200,
duration: 1.5,
description: 'Player performed double jump at level 3'
}
);

Common Telemetry Patterns

// Game start
await hyve.sendTelemetry(
'game', 'gameplay', 'start', 'level_1', null, null,
{ mode: 'campaign' }
);

// Game end
await hyve.sendTelemetry(
'game', 'gameplay', 'end', null, null, null,
{ score, duration: gameTime, description: `Score: ${score}` }
);

// Level complete
await hyve.sendTelemetry(
'game', 'level', 'complete', `level_${levelNum}`, null, null,
{ score, stars: 3, description: `Level ${levelNum} completed` }
);

// Achievement unlock
await hyve.sendTelemetry(
'game', 'achievement', 'unlock', achievementId, null, null,
{ timestamp: Date.now(), description: achievementName }
);

// Player action
await hyve.sendTelemetry(
'game', 'player', 'action', 'power_up', powerUpType, null,
{ location: { x, y }, description: `Collected ${powerUpType}` }
);

API Reference

Authentication Methods

MethodReturnsDescription
authenticateFromUrl()Promise<boolean>Authenticate from URL parameters
isAuthenticated()booleanCheck if user is authenticated
getUserId()string | nullGet authenticated user's ID
getSessionId()stringGet current session ID

Telemetry Methods

MethodParametersReturnsDescription
sendTelemetry(location, category, action, subCategory?, subAction?, details?, additionalData?)string, string, string, string|null, string|null, string|null, object|nullPromise<boolean>Send telemetry event with full control

Telemetry Fields

When sent to the backend, the telemetry event includes these fields (all are always present):

FieldTypeDescription
session_idstringUnique session identifier (auto-generated)
hyve_user_idstringUser's wallet address or 'anonymous'
event_locationstringWhere the event occurred (required)
event_categorystringMain category of event (required)
event_actionstringAction taken (required)
event_sub_categorystring | nullSub-category for granular classification
event_sub_actionstring | nullSub-action for detailed tracking
event_detailsstring | nullJSON stringified additional data or description

Additional Data Structure

interface TelemetryAdditionalData {
[key: string]: any; // Additional data (will be JSON stringified into event_details)
}

Utility Methods

MethodParametersReturnsDescription
getClient()NoneHyveClientGet underlying SDK client instance
configure(config)HyvePhaserPluginConfigvoidUpdate plugin configuration

Events

The plugin emits Phaser events that you can listen to:

import { HyveEvents } from '@hyve-sdk/phaser';

// Listen for authentication completion
this.game.events.on(HyveEvents.AUTHENTICATED, (event) => {
if (event.success) {
console.log('Authentication successful!');
console.log('User ID:', event.userId);
} else {
console.error('Authentication failed:', event.error);
}
});

// Listen for successful telemetry
this.game.events.on(HyveEvents.TELEMETRY_SENT, (event) => {
console.log('Event tracked:', event.eventName);
});

// Listen for telemetry errors
this.game.events.on(HyveEvents.TELEMETRY_ERROR, (event) => {
console.error('Telemetry error:', event.eventName, event.error);
});

// Plugin ready event
this.game.events.on(HyveEvents.PLUGIN_READY, (plugin) => {
console.log('Plugin is ready to use!');
});

Complete Example

Boot Scene with Plugin Integration

import { Scene } from 'phaser';
import HyvePhaserPlugin, { HyveEvents } from '@hyve-sdk/phaser';

export class BootScene extends Scene {
private hyve!: HyvePhaserPlugin;

constructor() {
super('Boot');
}

init() {
// Get plugin reference
this.hyve = this.plugins.get('HyvePhaserPlugin') as HyvePhaserPlugin;

// Listen for authentication
this.game.events.once(HyveEvents.AUTHENTICATED, (event) => {
if (event.success) {
// Store user info for other scenes
this.registry.set('userId', event.userId);
this.registry.set('authenticated', true);

// Track successful login
this.hyve.sendTelemetry(
'app',
'auth',
'login',
null,
null,
null,
{ method: 'url_params', description: 'User authenticated via URL params' }
);
}
});
}

preload() {
// Load game assets
this.load.image('logo', 'assets/logo.png');
}

create() {
// Check authentication status
if (this.hyve.isAuthenticated()) {
console.log('Welcome back,', this.hyve.getUserId());
}

// Track game start
this.hyve.sendTelemetry(
'game',
'gameplay',
'start',
'my-awesome-game',
null,
null,
{
version: '1.0.0',
platform: 'web'
}
);

// Proceed to menu
this.scene.start('MainMenu');
}
}

Best Practices

1. Environment-Based Configuration

// Use environment variables for sensitive data
const config = {
plugins: {
global: [{
key: 'HyvePhaserPlugin',
plugin: HyvePhaserPlugin,
start: true,
data: {
apiKey: process.env.NEXT_PUBLIC_HYVE_API_KEY,
isDev: process.env.NODE_ENV !== 'production',
debug: process.env.NODE_ENV !== 'production'
}
}]
}
};

2. Error Handling

// Always handle telemetry failures gracefully
try {
const success = await hyve.trackGameEnd('my-game', score);
if (!success) {
console.warn('Telemetry failed to send');
// Game continues normally
}
} catch (error) {
console.error('Telemetry error:', error);
// Don't let telemetry errors break the game
}

3. Batching High-Frequency Events

// For high-frequency events, consider batching
class GameScene extends Scene {
private pendingEvents: any[] = [];
private eventTimer?: Phaser.Time.TimerEvent;

create() {
// Send batched events every 5 seconds
this.eventTimer = this.time.addEvent({
delay: 5000,
callback: this.sendBatchedEvents,
callbackScope: this,
loop: true
});
}

trackAction(action: string, data: any) {
this.pendingEvents.push({ action, data, timestamp: Date.now() });
}

sendBatchedEvents() {
if (this.pendingEvents.length > 0) {
const hyve = this.plugins.get('HyvePhaserPlugin');
hyve.sendTelemetry(
'game',
'batch',
'events',
null,
null,
null,
{
events: this.pendingEvents,
description: `Batch of ${this.pendingEvents.length} events`
}
);
this.pendingEvents = [];
}
}
}

Troubleshooting

Plugin Not Loading

Problem: Plugin is undefined when trying to access it.

Solution:

// Ensure plugin is loaded before accessing
create() {
// Wait for next frame if needed
this.time.delayedCall(0, () => {
const hyve = this.plugins.get('HyvePhaserPlugin');
if (hyve) {
// Use plugin
}
});
}

Authentication Not Working

Problem: User is not being authenticated from URL parameters.

Checklist:

  1. Verify URL parameters are correct format
  2. Listen for AUTHENTICATED event for debugging
  3. Check browser console for errors
  4. Ensure the plugin is initialized before trying to authenticate
// Debug authentication
this.game.events.on(HyveEvents.AUTHENTICATED, (event) => {
console.log('Auth event:', event);
if (!event.success) {
console.error('Auth failed:', event.error);
}
});

Telemetry Not Sending

Problem: Telemetry events are not being sent.

Checklist:

  1. Verify API key is set correctly (check .env.local)
  2. Check network tab for failed requests to hyve.gg endpoints
  3. User authentication is optional - telemetry works with 'anonymous' user
  4. Listen for TELEMETRY_ERROR events
  5. Verify all required fields (location, category, action) are provided
// Debug telemetry
this.game.events.on(HyveEvents.TELEMETRY_ERROR, (event) => {
console.error('Telemetry failed:', event);
});

TypeScript Types Not Found

Problem: TypeScript cannot find plugin types.

Solution:

// Import types explicitly
import HyvePhaserPlugin, {
HyveEvents,
HyvePhaserPluginConfig
} from '@hyve-sdk/phaser';

// Type your plugin reference
const hyve = this.plugins.get('HyvePhaserPlugin') as HyvePhaserPlugin;

Migration Guide

From Manual SDK Integration

If you're migrating from manual SDK integration to the plugin:

Before (Manual SDK):

import { HyveClient } from '@hyve-sdk/js';

class GameScene extends Scene {
private client: HyveClient;

create() {
this.client = new HyveClient({ apiKey: 'key', isDev: true });
this.client.authenticateFromUrl();
// Manual telemetry
this.client.sendTelemetry(
'game', 'gameplay', 'start', null, null, null, null
);
}
}

After (Plugin):

class GameScene extends Scene {
create() {
const hyve = this.plugins.get('HyvePhaserPlugin');
// Authentication is automatic
// Same telemetry API
hyve.sendTelemetry(
'game', 'gameplay', 'start', null, null, null, null
);
}
}