UNPKG

expo-game-center

Version:

A comprehensive Expo module for iOS Game Center integration, providing authentication, leaderboards, achievements, and native UI presentation.

264 lines (227 loc) 7.7 kB
import { useState, useEffect, useCallback, useRef } from 'react'; import { Platform } from 'react-native'; import { GameCenterService, GameCenterConfig } from '../GameCenterService'; import { ConnectionStatus, ConnectionState } from '../GameCenterConnectionManager'; import { GameCenterPlayer } from '../index'; export interface UseGameCenterOptions extends GameCenterConfig { autoInitialize?: boolean; autoAuthenticate?: boolean; } export interface UseGameCenterReturn { // Status status: ConnectionStatus; isReady: boolean; isLoading: boolean; error: string | null; // Player info player: GameCenterPlayer | null; // Actions initialize: () => Promise<void>; authenticate: () => Promise<boolean>; submitScore: (score: number, leaderboardKey: string) => Promise<boolean>; reportAchievement: (achievementKey: string, progress?: number) => Promise<boolean>; showLeaderboard: (leaderboardKey: string) => Promise<void>; showAchievements: () => Promise<void>; showGameCenter: () => Promise<void>; reset: () => void; // Utilities getStateDescription: () => string; isPlatformSupported: boolean; } export function useGameCenter(options: UseGameCenterOptions = {}): UseGameCenterReturn { const { autoInitialize = true, autoAuthenticate = false, enableLogging = false, ...config } = options; const serviceRef = useRef<GameCenterService | null>(null); const [status, setStatus] = useState<ConnectionStatus>({ state: 'uninitialized', isAvailable: false, isAuthenticated: false, player: null, lastError: null, lastCheck: 0, }); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState<string | null>(null); // Initialize service const getService = useCallback(() => { if (!serviceRef.current) { serviceRef.current = new GameCenterService({ ...config, enableLogging, }); } return serviceRef.current; }, [config, enableLogging]); // Initialize GameCenter const initialize = useCallback(async () => { if (Platform.OS !== 'ios') { setError('GameCenter is only available on iOS'); return; } setIsLoading(true); setError(null); try { const service = getService(); const newStatus = await service.initialize(); setStatus(newStatus); if (newStatus.lastError) { setError(newStatus.lastError); } } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Initialization failed'; setError(errorMessage); console.error('[useGameCenter] Initialization error:', err); } finally { setIsLoading(false); } }, [getService]); // Authenticate with GameCenter const authenticate = useCallback(async (): Promise<boolean> => { setIsLoading(true); setError(null); try { const service = getService(); const success = await service.authenticate(); // Update status after authentication attempt const newStatus = service.getStatus(); setStatus(newStatus); if (!success && newStatus.lastError) { setError(newStatus.lastError); } return success; } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Authentication failed'; setError(errorMessage); console.error('[useGameCenter] Authentication error:', err); return false; } finally { setIsLoading(false); } }, [getService]); // Submit score const submitScore = useCallback(async (score: number, leaderboardKey: string): Promise<boolean> => { try { const service = getService(); const result = await service.submitScore(score, leaderboardKey); if (!result.success && result.error) { setError(result.error); } return result.success; } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Score submission failed'; setError(errorMessage); console.error('[useGameCenter] Score submission error:', err); return false; } }, [getService]); // Report achievement const reportAchievement = useCallback(async (achievementKey: string, progress = 100): Promise<boolean> => { try { const service = getService(); const result = await service.reportAchievement(achievementKey, progress); if (!result.success && result.error) { setError(result.error); } return result.success; } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Achievement reporting failed'; setError(errorMessage); console.error('[useGameCenter] Achievement reporting error:', err); return false; } }, [getService]); // Show leaderboard const showLeaderboard = useCallback(async (leaderboardKey: string): Promise<void> => { try { const service = getService(); await service.showLeaderboard(leaderboardKey); } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Failed to show leaderboard'; setError(errorMessage); console.error('[useGameCenter] Show leaderboard error:', err); } }, [getService]); // Show achievements const showAchievements = useCallback(async (): Promise<void> => { try { const service = getService(); await service.showAchievements(); } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Failed to show achievements'; setError(errorMessage); console.error('[useGameCenter] Show achievements error:', err); } }, [getService]); // Show GameCenter const showGameCenter = useCallback(async (): Promise<void> => { try { const service = getService(); await service.showGameCenter(); } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Failed to show GameCenter'; setError(errorMessage); console.error('[useGameCenter] Show GameCenter error:', err); } }, [getService]); // Reset const reset = useCallback(() => { const service = getService(); service.reset(); setStatus(service.getStatus()); setError(null); }, [getService]); // Get state description const getStateDescription = useCallback((): string => { const service = getService(); return service.getConnectionStateDescription(status.state); }, [getService, status.state]); // Set up status listener useEffect(() => { const service = getService(); const removeListener = service.addStatusListener((newStatus: ConnectionStatus) => { setStatus(newStatus); if (newStatus.lastError) { setError(newStatus.lastError); } }); return removeListener; }, [getService]); // Auto-initialize useEffect(() => { if (autoInitialize && Platform.OS === 'ios') { initialize(); } }, [autoInitialize, initialize]); // Auto-authenticate after initialization useEffect(() => { if (autoAuthenticate && status.state === 'not_available' && status.isAvailable) { authenticate(); } }, [autoAuthenticate, status.state, status.isAvailable, authenticate]); return { // Status status, isReady: status.state === 'authenticated' && status.isAuthenticated, isLoading, error, // Player info player: status.player, // Actions initialize, authenticate, submitScore, reportAchievement, showLeaderboard, showAchievements, showGameCenter, reset, // Utilities getStateDescription, isPlatformSupported: Platform.OS === 'ios', }; } export default useGameCenter;