import 'dart:convert'; import 'dart:developer'; import 'package:flutter/foundation.dart'; import 'package:mchess/api/websocket_message.dart'; import 'package:mchess/chess_bloc/chess_bloc.dart'; import 'package:mchess/chess_bloc/chess_events.dart'; import 'package:mchess/api/register.dart'; import 'package:mchess/chess_bloc/chess_position.dart'; import 'package:mchess/connection_cubit/connection_cubit.dart'; import 'package:mchess/utils/chess_utils.dart'; import 'package:web_socket_channel/web_socket_channel.dart'; class ServerConnection { late WebSocketChannel channel; late bool wasConnected = false; late int counter = 0; Stream broadcast = const Stream.empty(); static final ServerConnection _instance = ServerConnection._internal(); ServerConnection._internal() { log("ServerConnection._internal constructor is called"); } factory ServerConnection() { return _instance; } factory ServerConnection.getInstance() { return ServerConnection(); } void send(String message) { channel.sink.add(message); counter++; } void connect(String playerID, lobbyID, String? passphrase) { if (kDebugMode) { channel = WebSocketChannel.connect(Uri.parse('ws://localhost:8080/api/ws')); } else { channel = WebSocketChannel.connect( Uri.parse('wss://chess.sw-gross.de:9999/api/ws')); } send( jsonEncode( WebsocketMessageIdentifyPlayer( playerID: (playerID), lobbyID: (lobbyID), passphrase: (passphrase), ), ), ); log(channel.closeCode.toString()); broadcast = channel.stream.asBroadcastStream(); broadcast.listen(handleIncomingData); } void handleIncomingData(dynamic data) { log("Data received:"); log(data); var apiMessage = ApiWebsocketMessage.fromJson(jsonDecode(data)); switch (apiMessage.type) { case MessageType.colorDetermined: handleIncomingColorDeterminedMessage(apiMessage); break; case MessageType.move: handleIncomingMoveMessage(apiMessage); break; case MessageType.invalidMove: handleInvalidMoveMessage(apiMessage); } } void handleIncomingColorDeterminedMessage(ApiWebsocketMessage apiMessage) { ConnectionCubit.getInstance().opponentConnected(); ChessBloc.getInstance().add(InitBoard()); ChessBloc.getInstance().add( ColorDetermined(myColor: ChessColor.fromApiColor(apiMessage.color!))); } void handleIncomingMoveMessage(ApiWebsocketMessage apiMessage) { var move = ChessMove.fromApiMove(apiMessage.move!); if (apiMessage.position != null) { ChessBloc.getInstance().add(ReceivedPosition( position: ChessPosition.getInstance().fromPGNString(apiMessage.position!))); } ChessBloc.getInstance() .add(ReceivedMove(startSquare: move.from, endSquare: move.to)); } void handleInvalidMoveMessage(ApiWebsocketMessage apiMessage) { log("invalid move message received, with move: ${apiMessage.move.toString()}"); ChessBloc.getInstance() .add(InvalidMovePlayed(move: ChessMove.fromApiMove(apiMessage.move!))); } }