158 lines
No EOL
4.8 KiB
Dart
158 lines
No EOL
4.8 KiB
Dart
// ===========================================================================
|
|
// FILE: lib/services/multiplayer_service.dart
|
|
// ===========================================================================
|
|
|
|
import 'dart:math';
|
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
import 'package:firebase_auth/firebase_auth.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:share_plus/share_plus.dart';
|
|
|
|
class MultiplayerService {
|
|
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
|
|
final FirebaseAuth _auth = FirebaseAuth.instance;
|
|
|
|
CollectionReference get _gamesCollection => _firestore.collection('games');
|
|
CollectionReference get _invitesCollection => _firestore.collection('invites');
|
|
|
|
Future<String> createGameRoom(int boardRadius, String hostName, String shapeName, bool isTimeMode, {bool isPublic = true}) async {
|
|
String roomCode = _generateRoomCode();
|
|
int randomSeed = Random().nextInt(1000000);
|
|
|
|
await _gamesCollection.doc(roomCode).set({
|
|
'status': 'waiting',
|
|
'radius': boardRadius,
|
|
'createdAt': FieldValue.serverTimestamp(),
|
|
'players': ['host'],
|
|
'turn': 'host',
|
|
'moves': [],
|
|
'seed': randomSeed,
|
|
'hostName': hostName,
|
|
'hostUid': _auth.currentUser?.uid,
|
|
'guestName': '',
|
|
'shape': shapeName,
|
|
'timeMode': isTimeMode,
|
|
'isPublic': isPublic,
|
|
'p1_reaction': null,
|
|
'p2_reaction': null,
|
|
'p1_rematch': false,
|
|
'p2_rematch': false,
|
|
});
|
|
|
|
return roomCode;
|
|
}
|
|
|
|
Future<Map<String, dynamic>?> joinGameRoom(String roomCode, String guestName) async {
|
|
DocumentSnapshot doc = await _gamesCollection.doc(roomCode).get();
|
|
|
|
if (doc.exists && doc['status'] == 'waiting') {
|
|
await _gamesCollection.doc(roomCode).update({
|
|
'status': 'playing',
|
|
'players': FieldValue.arrayUnion(['guest']),
|
|
'guestName': guestName,
|
|
});
|
|
return doc.data() as Map<String, dynamic>;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
Stream<QuerySnapshot> getPublicRooms() {
|
|
return _gamesCollection
|
|
.where('status', isEqualTo: 'waiting')
|
|
.where('isPublic', isEqualTo: true)
|
|
.snapshots();
|
|
}
|
|
|
|
void shareInviteLink(String roomCode) {
|
|
// ECCO IL TUO SMART LINK FIREBASE!
|
|
String smartLink = "https://tetraq-32a4a.web.app";
|
|
|
|
String message = "Ehi! Giochiamo a TetraQ? 🎮\n\n"
|
|
"Apri l'app e inserisci il codice stanza:\n"
|
|
"👉 $roomCode\n\n"
|
|
"Oppure clicca qui se il tuo telefono lo supporta:\n"
|
|
"tetraq://join?code=$roomCode\n\n"
|
|
"Non hai ancora il gioco? Scaricalo da qui:\n"
|
|
"$smartLink";
|
|
|
|
Share.share(message);
|
|
}
|
|
|
|
Stream<DocumentSnapshot> listenToRoom(String roomCode) {
|
|
return _gamesCollection.doc(roomCode).snapshots();
|
|
}
|
|
|
|
String _generateRoomCode() {
|
|
const chars = 'ACDEFGHJKLMNPQRSTUVWXYZ2345679';
|
|
final random = Random();
|
|
return String.fromCharCodes(Iterable.generate(
|
|
5, (_) => chars.codeUnitAt(random.nextInt(chars.length)),
|
|
));
|
|
}
|
|
|
|
Future<void> sendReaction(String roomCode, bool isHost, String reaction) async {
|
|
try {
|
|
String prefix = isHost ? 'p1' : 'p2';
|
|
await _gamesCollection.doc(roomCode).update({
|
|
'${prefix}_reaction': reaction,
|
|
'${prefix}_reaction_time': FieldValue.serverTimestamp(),
|
|
});
|
|
} catch (e) {
|
|
debugPrint("Errore invio reazione: $e");
|
|
}
|
|
}
|
|
|
|
Future<void> requestRematch(String roomCode, bool isHost) async {
|
|
try {
|
|
String prefix = isHost ? 'p1' : 'p2';
|
|
await _gamesCollection.doc(roomCode).update({
|
|
'${prefix}_rematch': true,
|
|
});
|
|
} catch (e) {
|
|
debugPrint("Errore richiesta rivincita: $e");
|
|
}
|
|
}
|
|
|
|
Future<void> resetMatch(String roomCode, int newRadius, String newShape, int newSeed) async {
|
|
try {
|
|
await _gamesCollection.doc(roomCode).update({
|
|
'status': 'playing',
|
|
'moves': [],
|
|
'seed': newSeed,
|
|
'radius': newRadius,
|
|
'shape': newShape,
|
|
'p1_rematch': false,
|
|
'p2_rematch': false,
|
|
'p1_reaction': null,
|
|
'p2_reaction': null,
|
|
});
|
|
} catch (e) {
|
|
debugPrint("Errore reset partita: $e");
|
|
}
|
|
}
|
|
|
|
Future<void> sendInvite(String targetUid, String roomCode, String hostName) async {
|
|
try {
|
|
await _invitesCollection.add({
|
|
'targetUid': targetUid,
|
|
'hostName': hostName,
|
|
'roomCode': roomCode,
|
|
'timestamp': FieldValue.serverTimestamp(),
|
|
});
|
|
} catch(e) {
|
|
debugPrint("Errore invio invito: $e");
|
|
}
|
|
}
|
|
|
|
Stream<QuerySnapshot> listenForInvites(String myUid) {
|
|
return _invitesCollection.where('targetUid', isEqualTo: myUid).snapshots();
|
|
}
|
|
|
|
Future<void> deleteInvite(String inviteId) async {
|
|
try {
|
|
await _invitesCollection.doc(inviteId).delete();
|
|
} catch(e) {
|
|
debugPrint("Errore cancellazione invito: $e");
|
|
}
|
|
}
|
|
} |