// =========================================================================== // 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'); // --- MODIFICA QUI: bool isTimeMode รจ diventato String timeMode --- Future createGameRoom(int boardRadius, String hostName, String shapeName, String timeMode, {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': timeMode, // Salva la stringa ('fixed', 'relax' o 'dynamic') 'isPublic': isPublic, 'p1_reaction': null, 'p2_reaction': null, 'p1_rematch': false, 'p2_rematch': false, }); return roomCode; } Future?> 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; } return null; } Stream 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 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 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 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 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 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 listenForInvites(String myUid) { return _invitesCollection.where('targetUid', isEqualTo: myUid).snapshots(); } Future deleteInvite(String inviteId) async { try { await _invitesCollection.doc(inviteId).delete(); } catch(e) { debugPrint("Errore cancellazione invito: $e"); } } }