Globalpulse

GlobalPulse - Live Configuration

GlobalPulse is Globio's live configuration service. Update game settings, feature flags, and content without releasing app updates.

🚀 Quick Start

import { GlobalPulse } from '@stanlink/globio'
 
const config = new GlobalPulse({
  apiKey: 'your-api-key',
  projectId: 'your-project-id'
})
 
// Get configuration value
const eventActive = await config.getValue('christmas_event', false)
if (eventActive) {
  showChristmasContent()
}

⚙️ Configuration Management

Basic Values

// Get string value
const welcomeMessage = await config.getValue('welcome_message', 'Welcome to the game!')
 
// Get number value
const maxLevel = await config.getValue('max_level', 100)
 
// Get boolean value
const newFeatureEnabled = await config.getValue('new_feature_enabled', false)
 
// Get object value
const gameSettings = await config.getValue('game_settings', {
  difficulty: 'normal',
  soundEnabled: true,
  musicVolume: 0.8
})

Real-time Updates

// Listen for configuration changes
const unsubscribe = config.onConfigChange((key, value) => {
  console.log(`Config updated: ${key} = ${value}`)
  
  switch (key) {
    case 'maintenance_mode':
      if (value) {
        showMaintenanceMessage()
      } else {
        hideMaintenanceMessage()
      }
      break
    case 'daily_bonus':
      updateDailyBonusUI(value)
      break
  }
})
 
// Stop listening
unsubscribe()

🎮 Gaming Use Cases

Feature Flags

// Enable/disable features remotely
const features = {
  newGameMode: await config.getValue('new_game_mode_enabled', false),
  socialFeatures: await config.getValue('social_features_enabled', true),
  inAppPurchases: await config.getValue('iap_enabled', true),
  leaderboards: await config.getValue('leaderboards_enabled', true)
}
 
// Conditionally show UI elements
if (features.newGameMode) {
  showNewGameModeButton()
}
 
if (features.socialFeatures) {
  enableFriendSystem()
}

Live Events

// Manage live events
const currentEvent = await config.getValue('current_event', null)
 
if (currentEvent) {
  const eventConfig = await config.getValue(`events.${currentEvent}`, {})
  
  // Apply event settings
  applyEventSettings({
    name: eventConfig.name,
    startTime: new Date(eventConfig.startTime),
    endTime: new Date(eventConfig.endTime),
    rewards: eventConfig.rewards,
    specialRules: eventConfig.specialRules
  })
}
 
// Listen for event changes
config.onConfigChange('current_event', (eventName) => {
  if (eventName) {
    startEvent(eventName)
  } else {
    endCurrentEvent()
  }
})

Game Balance

// Adjust game balance without updates
const gameBalance = {
  playerHealth: await config.getValue('player_health', 100),
  enemyDamage: await config.getValue('enemy_damage', 25),
  coinDropRate: await config.getValue('coin_drop_rate', 0.3),
  experienceMultiplier: await config.getValue('xp_multiplier', 1.0)
}
 
// Apply balance changes
player.maxHealth = gameBalance.playerHealth
enemies.forEach(enemy => {
  enemy.damage = gameBalance.enemyDamage
})

A/B Testing

// A/B test different game mechanics
const playerGroup = await config.getValue(`ab_test_group_${playerId}`, 'A')
const testConfig = await config.getValue(`ab_test_${playerGroup}`, {})
 
switch (playerGroup) {
  case 'A':
    // Original game mechanics
    setupOriginalMechanics()
    break
  case 'B':
    // New game mechanics
    setupNewMechanics(testConfig)
    break
}
 
// Track A/B test results
trackEvent('ab_test_interaction', {
  group: playerGroup,
  action: 'game_completed',
  result: gameResult
})

🔧 Advanced Features

Conditional Configuration

// Configuration based on user properties
const userTier = getCurrentUserTier() // 'free', 'premium', 'vip'
const adFrequency = await config.getValue(`ad_frequency_${userTier}`, {
  free: 30,    // Every 30 seconds
  premium: 120, // Every 2 minutes
  vip: 0       // No ads
})
 
// Configuration based on platform
const platform = getPlatform() // 'ios', 'android', 'web'
const storeConfig = await config.getValue(`store_config_${platform}`, {})

Scheduled Changes

// Check for scheduled configuration changes
const scheduledConfigs = await config.getValue('scheduled_configs', [])
 
scheduledConfigs.forEach(scheduledConfig => {
  const { key, value, activateAt } = scheduledConfig
  const activationTime = new Date(activateAt)
  
  if (Date.now() >= activationTime.getTime()) {
    // Apply scheduled configuration
    applyConfigValue(key, value)
  }
})

Configuration Validation

// Validate configuration values
function validateConfig(key, value, expectedType) {
  if (typeof value !== expectedType) {
    console.warn(`Invalid config type for ${key}: expected ${expectedType}, got ${typeof value}`)
    return false
  }
  return true
}
 
// Safe configuration getter
async function getSafeConfig(key, defaultValue, validator) {
  try {
    const value = await config.getValue(key, defaultValue)
    
    if (validator && !validator(value)) {
      console.warn(`Config validation failed for ${key}, using default`)
      return defaultValue
    }
    
    return value
  } catch (error) {
    console.error(`Failed to get config ${key}:`, error)
    return defaultValue
  }
}
 
// Usage
const maxPlayers = await getSafeConfig('max_players', 4, (value) => {
  return typeof value === 'number' && value > 0 && value <= 100
})

📱 Platform Examples

Unity C#

// Unity configuration
public class GameConfig : MonoBehaviour {
    void Start() {
        LoadGameConfig();
    }
    
    async void LoadGameConfig() {
        // Get configuration values
        bool eventActive = await GlobalPulse.GetBool("summer_event", false);
        int maxLevel = await GlobalPulse.GetInt("max_level", 50);
        float difficultyMultiplier = await GlobalPulse.GetFloat("difficulty_multiplier", 1.0f);
        
        // Apply configuration
        if (eventActive) {
            EnableSummerEvent();
        }
        
        GameManager.MaxLevel = maxLevel;
        GameManager.DifficultyMultiplier = difficultyMultiplier;
    }
    
    void OnEnable() {
        // Listen for config changes
        GlobalPulse.OnConfigChanged += OnConfigChanged;
    }
    
    void OnConfigChanged(string key, object value) {
        switch (key) {
            case "maintenance_mode":
                if ((bool)value) {
                    ShowMaintenanceScreen();
                }
                break;
        }
    }
}

Flutter/Dart

// Flutter configuration
class GameConfigService {
  static Future<void> loadConfig() async {
    // Load game configuration
    final eventActive = await GlobalPulse.getBool('weekend_bonus', false);
    final bonusMultiplier = await GlobalPulse.getDouble('bonus_multiplier', 1.0);
    
    // Apply configuration
    if (eventActive) {
      GameState.bonusMultiplier = bonusMultiplier;
    }
  }
  
  static void listenForChanges() {
    GlobalPulse.onConfigChange.listen((ConfigChange change) {
      switch (change.key) {
        case 'new_feature_enabled':
          if (change.value as bool) {
            _enableNewFeature();
          }
          break;
      }
    });
  }
}

💡 Best Practices

Configuration Structure

// ✅ Good: Organized configuration
const config = {
  // Game balance
  'game.player_health': 100,
  'game.enemy_damage': 25,
  'game.coin_drop_rate': 0.3,
  
  // Features
  'features.new_game_mode': false,
  'features.social_system': true,
  'features.leaderboards': true,
  
  // Events
  'events.current': 'halloween_2024',
  'events.halloween_2024.active': true,
  'events.halloween_2024.bonus_xp': 2.0,
  
  // A/B Tests
  'ab_test.new_ui.enabled': true,
  'ab_test.new_ui.percentage': 50
}
 
// ❌ Avoid: Flat, unclear structure
const config = {
  'health': 100,
  'damage': 25,
  'event': true,
  'test': 50
}

Caching Strategy

// Cache configuration with TTL
class ConfigCache {
  constructor(ttl = 300000) { // 5 minutes
    this.cache = new Map()
    this.ttl = ttl
  }
  
  async get(key, defaultValue) {
    const cached = this.cache.get(key)
    
    if (cached && Date.now() - cached.timestamp &lt; this.ttl) {
      return cached.value
    }
    
    const value = await config.getValue(key, defaultValue)
    this.cache.set(key, {
      value,
      timestamp: Date.now()
    })
    
    return value
  }
  
  invalidate(key) {
    this.cache.delete(key)
  }
}

Next: Learn about GlobalSync Multiplayer