-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Integrate games cookbook recipes with the code excerpts machinery (#9950
) Makes the code featured in the new game-related cookbooks CI-tested. _Issues fixed by this PR (if any):_ Fixes #9822. ## Presubmit checklist - [x] This PR doesn’t contain automatically generated corrections (Grammarly or similar). - [x] This PR follows the [Google Developer Documentation Style Guidelines](https://developers.google.com/style) — for example, it doesn’t use _i.e._ or _e.g._, and it avoids _I_ and _we_ (first person). - [x] This PR uses [semantic line breaks](https://github.com/dart-lang/site-shared/blob/main/doc/writing-for-dart-and-flutter-websites.md#semantic-line-breaks) of 80 characters or fewer.
- Loading branch information
Showing
21 changed files
with
885 additions
and
108 deletions.
There are no files selected for viewing
5 changes: 5 additions & 0 deletions
5
examples/cookbook/games/achievements_leaderboards/analysis_options.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Take our settings from the example_utils analysis_options.yaml file. | ||
# If necessary for a particular example, this file can also include | ||
# overrides for individual lints. | ||
|
||
include: package:example_utils/analysis.yaml |
113 changes: 113 additions & 0 deletions
113
examples/cookbook/games/achievements_leaderboards/lib/games_services_controller.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import 'dart:async'; | ||
|
||
import 'package:games_services/games_services.dart'; | ||
import 'package:logging/logging.dart'; | ||
|
||
/// Allows awarding achievements and leaderboard scores, | ||
/// and also showing the platforms' UI overlays for achievements | ||
/// and leaderboards. | ||
/// | ||
/// A facade of `package:games_services`. | ||
class GamesServicesController { | ||
static final Logger _log = Logger('GamesServicesController'); | ||
|
||
final Completer<bool> _signedInCompleter = Completer(); | ||
|
||
Future<bool> get signedIn => _signedInCompleter.future; | ||
|
||
/// Unlocks an achievement on Game Center / Play Games. | ||
/// | ||
/// You must provide the achievement ids via the [iOS] and [android] | ||
/// parameters. | ||
/// | ||
/// Does nothing when the game isn't signed into the underlying | ||
/// games service. | ||
Future<void> awardAchievement( | ||
{required String iOS, required String android}) async { | ||
if (!await signedIn) { | ||
_log.warning('Trying to award achievement when not logged in.'); | ||
return; | ||
} | ||
|
||
try { | ||
await GamesServices.unlock( | ||
achievement: Achievement( | ||
androidID: android, | ||
iOSID: iOS, | ||
), | ||
); | ||
} catch (e) { | ||
_log.severe('Cannot award achievement: $e'); | ||
} | ||
} | ||
|
||
/// Signs into the underlying games service. | ||
Future<void> initialize() async { | ||
try { | ||
await GamesServices.signIn(); | ||
// The API is unclear so we're checking to be sure. The above call | ||
// returns a String, not a boolean, and there's no documentation | ||
// as to whether every non-error result means we're safely signed in. | ||
final signedIn = await GamesServices.isSignedIn; | ||
_signedInCompleter.complete(signedIn); | ||
} catch (e) { | ||
_log.severe('Cannot log into GamesServices: $e'); | ||
_signedInCompleter.complete(false); | ||
} | ||
} | ||
|
||
/// Launches the platform's UI overlay with achievements. | ||
Future<void> showAchievements() async { | ||
if (!await signedIn) { | ||
_log.severe('Trying to show achievements when not logged in.'); | ||
return; | ||
} | ||
|
||
try { | ||
await GamesServices.showAchievements(); | ||
} catch (e) { | ||
_log.severe('Cannot show achievements: $e'); | ||
} | ||
} | ||
|
||
/// Launches the platform's UI overlay with leaderboard(s). | ||
Future<void> showLeaderboard() async { | ||
if (!await signedIn) { | ||
_log.severe('Trying to show leaderboard when not logged in.'); | ||
return; | ||
} | ||
|
||
try { | ||
await GamesServices.showLeaderboards( | ||
// TODO: When ready, change both these leaderboard IDs. | ||
iOSLeaderboardID: 'some_id_from_app_store', | ||
androidLeaderboardID: 'sOmE_iD_fRoM_gPlAy', | ||
); | ||
} catch (e) { | ||
_log.severe('Cannot show leaderboard: $e'); | ||
} | ||
} | ||
|
||
/// Submits [score] to the leaderboard. | ||
Future<void> submitLeaderboardScore(int score) async { | ||
if (!await signedIn) { | ||
_log.warning('Trying to submit leaderboard when not logged in.'); | ||
return; | ||
} | ||
|
||
_log.info('Submitting $score to leaderboard.'); | ||
|
||
try { | ||
await GamesServices.submitScore( | ||
score: Score( | ||
// TODO: When ready, change these leaderboard IDs. | ||
iOSLeaderboardID: 'some_id_from_app_store', | ||
androidLeaderboardID: 'sOmE_iD_fRoM_gPlAy', | ||
value: score, | ||
), | ||
); | ||
} catch (e) { | ||
_log.severe('Cannot submit leaderboard score: $e'); | ||
} | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
examples/cookbook/games/achievements_leaderboards/lib/various.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// ignore_for_file: unused_catch_clause | ||
|
||
import 'package:flutter/services.dart'; | ||
import 'package:games_services/games_services.dart'; | ||
|
||
void main() async { | ||
// #docregion signIn | ||
try { | ||
await GamesServices.signIn(); | ||
} on PlatformException catch (e) { | ||
// ... deal with failures ... | ||
} | ||
// #enddocregion signIn | ||
|
||
// #docregion unlock | ||
await GamesServices.unlock( | ||
achievement: Achievement( | ||
androidID: 'your android id', | ||
iOSID: 'your ios id', | ||
), | ||
); | ||
// #enddocregion unlock | ||
|
||
// #docregion showAchievements | ||
await GamesServices.showAchievements(); | ||
// #enddocregion showAchievements | ||
|
||
// #docregion submitScore | ||
await GamesServices.submitScore( | ||
score: Score( | ||
iOSLeaderboardID: 'some_id_from_app_store', | ||
androidLeaderboardID: 'sOmE_iD_fRoM_gPlAy', | ||
value: 100, | ||
), | ||
); | ||
// #enddocregion submitScore | ||
|
||
// #docregion showLeaderboards | ||
await GamesServices.showLeaderboards( | ||
iOSLeaderboardID: 'some_id_from_app_store', | ||
androidLeaderboardID: 'sOmE_iD_fRoM_gPlAy', | ||
); | ||
// #enddocregion showLeaderboards | ||
} |
19 changes: 19 additions & 0 deletions
19
examples/cookbook/games/achievements_leaderboards/pubspec.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
name: games_services_example | ||
description: Games services | ||
|
||
environment: | ||
sdk: ^3.2.0 | ||
|
||
dependencies: | ||
flutter: | ||
sdk: flutter | ||
|
||
games_services: ^4.0.0 | ||
logging: ^1.2.0 | ||
|
||
dev_dependencies: | ||
example_utils: | ||
path: ../../../example_utils | ||
|
||
flutter: | ||
uses-material-design: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
This is a stripped down version of the multiplayer sample | ||
in https://github.com/flutter/games/tree/main/samples/multiplayer. |
5 changes: 5 additions & 0 deletions
5
examples/cookbook/games/firestore_multiplayer/analysis_options.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Take our settings from the example_utils analysis_options.yaml file. | ||
# If necessary for a particular example, this file can also include | ||
# overrides for individual lints. | ||
|
||
include: package:example_utils/analysis.yaml |
80 changes: 80 additions & 0 deletions
80
examples/cookbook/games/firestore_multiplayer/lib/firebase_options.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// File generated by FlutterFire CLI. | ||
// ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members | ||
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; | ||
import 'package:flutter/foundation.dart' | ||
show defaultTargetPlatform, kIsWeb, TargetPlatform; | ||
|
||
/// Default [FirebaseOptions] for use with your Firebase apps. | ||
/// | ||
/// Example: | ||
/// ```dart | ||
/// import 'firebase_options.dart'; | ||
/// // ... | ||
/// await Firebase.initializeApp( | ||
/// options: DefaultFirebaseOptions.currentPlatform, | ||
/// ); | ||
/// ``` | ||
class DefaultFirebaseOptions { | ||
static FirebaseOptions get currentPlatform { | ||
if (kIsWeb) { | ||
return web; | ||
} | ||
switch (defaultTargetPlatform) { | ||
case TargetPlatform.android: | ||
return android; | ||
case TargetPlatform.iOS: | ||
return ios; | ||
case TargetPlatform.macOS: | ||
return macos; | ||
case TargetPlatform.windows: | ||
throw UnsupportedError( | ||
'DefaultFirebaseOptions have not been configured for windows - ' | ||
'you can reconfigure this by running the FlutterFire CLI again.', | ||
); | ||
case TargetPlatform.linux: | ||
throw UnsupportedError( | ||
'DefaultFirebaseOptions have not been configured for linux - ' | ||
'you can reconfigure this by running the FlutterFire CLI again.', | ||
); | ||
default: | ||
throw UnsupportedError( | ||
'DefaultFirebaseOptions are not supported for this platform.', | ||
); | ||
} | ||
} | ||
|
||
static const FirebaseOptions web = FirebaseOptions( | ||
apiKey: 'blahblahbla', | ||
appId: '1:123456:web:blahblahbla', | ||
messagingSenderId: '123456', | ||
projectId: 'card-game-deadbeef', | ||
authDomain: 'card-game-deadbeef.firebaseapp.com', | ||
storageBucket: 'card-game-deadbeef.appspot.com', | ||
); | ||
|
||
static const FirebaseOptions android = FirebaseOptions( | ||
apiKey: 'blahblahbla', | ||
appId: '1:123456:android:blahblahbla', | ||
messagingSenderId: '123456', | ||
projectId: 'card-game-deadbeef', | ||
storageBucket: 'card-game-deadbeef.appspot.com', | ||
); | ||
|
||
static const FirebaseOptions ios = FirebaseOptions( | ||
apiKey: 'blahblahbla', | ||
appId: '1:123456:ios:blahblahbla', | ||
messagingSenderId: '123456', | ||
projectId: 'card-game-deadbeef', | ||
storageBucket: 'card-game-deadbeef.appspot.com', | ||
iosBundleId: 'com.example.card', | ||
); | ||
|
||
static const FirebaseOptions macos = FirebaseOptions( | ||
apiKey: 'blahblahbla', | ||
appId: '1:123456:ios:blahblahbla', | ||
messagingSenderId: '123456', | ||
projectId: 'card-game-deadbeef', | ||
storageBucket: 'card-game-deadbeef.appspot.com', | ||
iosBundleId: 'com.example.card.RunnerTests', | ||
); | ||
} |
20 changes: 20 additions & 0 deletions
20
examples/cookbook/games/firestore_multiplayer/lib/game_internals/board_state.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// This file has only enough in it to satisfy `firestore_controller.dart`. | ||
|
||
import 'package:flutter/foundation.dart'; | ||
|
||
import 'playing_area.dart'; | ||
|
||
class BoardState { | ||
final VoidCallback onWin; | ||
|
||
final PlayingArea areaOne = PlayingArea(); | ||
|
||
final PlayingArea areaTwo = PlayingArea(); | ||
|
||
BoardState({required this.onWin}); | ||
|
||
void dispose() { | ||
areaOne.dispose(); | ||
areaTwo.dispose(); | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
examples/cookbook/games/firestore_multiplayer/lib/game_internals/playing_area.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// This file has only enough in it to satisfy `firestore_controller.dart`. | ||
|
||
import 'dart:async'; | ||
|
||
import 'playing_card.dart'; | ||
|
||
class PlayingArea { | ||
final List<PlayingCard> cards = []; | ||
|
||
final StreamController<void> _playerChanges = | ||
StreamController<void>.broadcast(); | ||
|
||
PlayingArea(); | ||
|
||
Stream<void> get playerChanges => _playerChanges.stream; | ||
|
||
void dispose() { | ||
_playerChanges.close(); | ||
} | ||
|
||
void replaceWith(List<PlayingCard> cards) { | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
examples/cookbook/games/firestore_multiplayer/lib/game_internals/playing_card.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// This file has only enough in it to satisfy `firestore_controller.dart`. | ||
class PlayingCard { | ||
const PlayingCard(); | ||
|
||
factory PlayingCard.fromJson(Map<String, dynamic> json) { | ||
return const PlayingCard(); | ||
} | ||
|
||
Map<String, dynamic> toJson() => { | ||
// Nothing | ||
}; | ||
} |
39 changes: 39 additions & 0 deletions
39
examples/cookbook/games/firestore_multiplayer/lib/main.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// ignore_for_file: directives_ordering, prefer_const_constructors | ||
|
||
import 'package:flutter/material.dart'; | ||
import 'package:provider/provider.dart'; | ||
|
||
// #docregion imports | ||
import 'package:cloud_firestore/cloud_firestore.dart'; | ||
import 'package:firebase_core/firebase_core.dart'; | ||
|
||
import 'firebase_options.dart'; | ||
// #enddocregion imports | ||
|
||
void main() async { | ||
// #docregion initializeApp | ||
WidgetsFlutterBinding.ensureInitialized(); | ||
|
||
await Firebase.initializeApp( | ||
options: DefaultFirebaseOptions.currentPlatform, | ||
); | ||
// #enddocregion initializeApp | ||
|
||
// #docregion runApp | ||
runApp( | ||
Provider.value( | ||
value: FirebaseFirestore.instance, | ||
child: MyApp(), | ||
), | ||
); | ||
// #enddocregion runApp | ||
} | ||
|
||
class MyApp extends StatelessWidget { | ||
const MyApp({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return const Placeholder(); | ||
} | ||
} |
Oops, something went wrong.