El Impostor v0.1 — app Flutter completa
Juego de deducción social para 3-20 jugadores. Modo un solo móvil completamente funcional. 1000 palabras en 10 categorías. Notas privadas, votación, adivinanza, revancha. Material 3 dark theme. Package: es.freetimelab.elimpostor
This commit is contained in:
147
lib/servicios/servicio_nearby.dart
Normal file
147
lib/servicios/servicio_nearby.dart
Normal file
@@ -0,0 +1,147 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
/// Tipos de mensajes en el protocolo P2P
|
||||
enum TipoMensaje {
|
||||
salaInfo,
|
||||
partidaInicio,
|
||||
fase,
|
||||
votacionResultado,
|
||||
partidaFin,
|
||||
unirse,
|
||||
voto,
|
||||
listo,
|
||||
}
|
||||
|
||||
/// Mensaje del protocolo P2P entre dispositivos
|
||||
class MensajeP2P {
|
||||
final TipoMensaje tipo;
|
||||
final Map<String, dynamic> datos;
|
||||
|
||||
MensajeP2P({required this.tipo, required this.datos});
|
||||
|
||||
String toJson() => json.encode({
|
||||
'tipo': tipo.name,
|
||||
'datos': datos,
|
||||
});
|
||||
|
||||
factory MensajeP2P.fromJson(String jsonStr) {
|
||||
final mapa = json.decode(jsonStr) as Map<String, dynamic>;
|
||||
return MensajeP2P(
|
||||
tipo: TipoMensaje.values.firstWhere((t) => t.name == mapa['tipo']),
|
||||
datos: mapa['datos'] as Map<String, dynamic>,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Servicio para conexiones P2P usando Google Nearby Connections API.
|
||||
///
|
||||
/// Este servicio encapsula toda la lógica de Nearby Connections.
|
||||
/// Requiere dispositivos Android físicos para funcionar.
|
||||
/// En la versión actual, se provee la estructura para integración futura.
|
||||
class ServicioNearby extends ChangeNotifier {
|
||||
bool _esHost = false;
|
||||
bool _conectado = false;
|
||||
String? _endpointId;
|
||||
final List<String> _dispositivos = [];
|
||||
|
||||
bool get esHost => _esHost;
|
||||
bool get conectado => _conectado;
|
||||
String? get endpointId => _endpointId;
|
||||
List<String> get dispositivos => List.unmodifiable(_dispositivos);
|
||||
|
||||
/// Inicia como host (anunciando el endpoint)
|
||||
Future<bool> iniciarHost(String nombreSala) async {
|
||||
// Nota: nearby_connections requiere permisos de ubicación y Bluetooth
|
||||
// que deben solicitarse antes de iniciar.
|
||||
// Implementación con el paquete nearby_connections:
|
||||
//
|
||||
// try {
|
||||
// await Nearby().startAdvertising(
|
||||
// nombreSala,
|
||||
// Strategy.P2P_STAR,
|
||||
// onConnectionInitiated: _onConexionIniciada,
|
||||
// onConnectionResult: _onResultadoConexion,
|
||||
// onDisconnected: _onDesconexion,
|
||||
// serviceId: 'es.freetimelab.elimpostor',
|
||||
// );
|
||||
// _esHost = true;
|
||||
// _endpointId = nombreSala;
|
||||
// notifyListeners();
|
||||
// return true;
|
||||
// } catch (e) {
|
||||
// debugPrint('Error iniciando host: $e');
|
||||
// return false;
|
||||
// }
|
||||
|
||||
_esHost = true;
|
||||
_endpointId = nombreSala;
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Conecta a un host escaneado via QR
|
||||
Future<bool> conectarAHost(String endpointId, String nombre) async {
|
||||
// Implementación con el paquete nearby_connections:
|
||||
//
|
||||
// try {
|
||||
// await Nearby().startDiscovery(
|
||||
// nombre,
|
||||
// Strategy.P2P_STAR,
|
||||
// onEndpointFound: (id, name, serviceId) {
|
||||
// Nearby().requestConnection(nombre, id,
|
||||
// onConnectionInitiated: _onConexionIniciada,
|
||||
// onConnectionResult: _onResultadoConexion,
|
||||
// onDisconnected: _onDesconexion,
|
||||
// );
|
||||
// },
|
||||
// onEndpointLost: (id) {},
|
||||
// serviceId: 'es.freetimelab.elimpostor',
|
||||
// );
|
||||
// return true;
|
||||
// } catch (e) {
|
||||
// debugPrint('Error conectando: $e');
|
||||
// return false;
|
||||
// }
|
||||
|
||||
_conectado = true;
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Envía un mensaje a un dispositivo específico
|
||||
Future<void> enviarMensaje(String endpointId, MensajeP2P mensaje) async {
|
||||
// Implementación:
|
||||
// final bytes = Uint8List.fromList(utf8.encode(mensaje.toJson()));
|
||||
// await Nearby().sendBytesPayload(endpointId, bytes);
|
||||
debugPrint('Enviar a $endpointId: ${mensaje.toJson()}');
|
||||
}
|
||||
|
||||
/// Envía un mensaje a todos los dispositivos conectados
|
||||
Future<void> enviarATodos(MensajeP2P mensaje) async {
|
||||
for (final id in _dispositivos) {
|
||||
await enviarMensaje(id, mensaje);
|
||||
}
|
||||
}
|
||||
|
||||
/// Desconecta y limpia
|
||||
Future<void> desconectar() async {
|
||||
// await Nearby().stopAllEndpoints();
|
||||
// await Nearby().stopAdvertising();
|
||||
// await Nearby().stopDiscovery();
|
||||
_esHost = false;
|
||||
_conectado = false;
|
||||
_endpointId = null;
|
||||
_dispositivos.clear();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Genera los datos para el código QR de conexión
|
||||
String generarDatosQR(String nombreSala) {
|
||||
return json.encode({
|
||||
'app': 'elimpostor',
|
||||
'endpoint': _endpointId,
|
||||
'sala': nombreSala,
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user