mchess-client/lib/connection/ws_connection.dart

152 lines
4.6 KiB
Dart
Raw Normal View History

2023-06-02 21:28:40 +00:00
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mchess/api/move.dart';
2023-06-08 15:10:48 +00:00
import 'package:mchess/api/websocket_message.dart';
import 'package:mchess/chess_bloc/chess_bloc.dart';
import 'package:mchess/chess_bloc/chess_events.dart';
2023-06-02 21:28:40 +00:00
import 'package:mchess/api/register.dart';
import 'package:mchess/chess_bloc/chess_position.dart';
2023-06-29 23:49:18 +00:00
import 'package:mchess/connection_cubit/connection_cubit.dart';
import 'package:mchess/utils/chess_router.dart';
2022-12-25 15:16:23 +00:00
import 'package:mchess/utils/chess_utils.dart';
import 'package:mchess/utils/config.dart' as config;
import 'package:web_socket_channel/web_socket_channel.dart';
class ServerConnection {
WebSocketChannel? channel;
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) {
if (channel == null) {
log("Sending on channel without initializing");
return;
}
channel!.sink.add(message);
}
2022-11-19 12:24:38 +00:00
2024-05-19 15:22:06 +00:00
void connect(String? passphrase) {
disconnectExistingConnection();
channel = WebSocketChannel.connect(Uri.parse(config.getWebsocketURL()));
2024-05-19 15:22:06 +00:00
send(jsonEncode(passphrase));
log(channel!.closeCode.toString());
broadcast = channel!.stream.asBroadcastStream();
2023-06-02 21:28:40 +00:00
broadcast.listen(handleIncomingData);
}
void disconnectExistingConnection() {
if (channel == null) return;
channel!.sink.close();
broadcast = const Stream.empty();
}
2023-06-02 21:28:40 +00:00
void handleIncomingData(dynamic data) {
2023-12-25 16:50:58 +00:00
log('${DateTime.now()}: Data received:');
2023-06-02 21:28:40 +00:00
log(data);
2023-06-08 15:10:48 +00:00
var apiMessage = ApiWebsocketMessage.fromJson(jsonDecode(data));
switch (apiMessage.type) {
case MessageType.boardState:
handleBoardStateMessage(apiMessage);
break;
2023-06-08 15:10:48 +00:00
case MessageType.colorDetermined:
handleIncomingColorDeterminedMessage(apiMessage);
2023-06-08 15:10:48 +00:00
break;
2023-06-02 21:28:40 +00:00
case MessageType.move:
2023-12-25 16:50:58 +00:00
log('ERROR: move message received');
break;
case MessageType.invalidMove:
handleInvalidMoveMessage(apiMessage);
case MessageType.gameEnded:
handleGameEndedMessage(apiMessage);
2023-06-08 15:10:48 +00:00
}
}
2023-06-02 21:28:40 +00:00
void handleBoardStateMessage(ApiWebsocketMessage apiMessage) {
ChessMove? move;
if (apiMessage.move != null) {
move = ChessMove.fromApiMove(apiMessage.move!);
}
if (apiMessage.position != null) {
ChessBloc.getInstance().add(
ReceivedBoardState(
2023-12-25 17:08:21 +00:00
startSquare: move?.from,
endSquare: move?.to,
position: ChessPositionManager.getInstance()
.fromPGNString(apiMessage.position!),
squareInCheck: ChessCoordinate.fromApiCoordinate(
apiMessage.squareInCheck ??
const ApiCoordinate(col: 0, row: 0)),
turnColor: ChessColor.fromApiColor(apiMessage.turnColor!)),
);
} else {
log('Error: no position received');
}
}
void handleIncomingColorDeterminedMessage(ApiWebsocketMessage apiMessage) {
2023-07-03 17:41:12 +00:00
ConnectionCubit.getInstance().opponentConnected();
ChessBloc.getInstance().add(InitBoard());
ChessBloc.getInstance().add(ColorDetermined(
myColor: ChessColor.fromApiColor(apiMessage.playerColor!)));
}
void handleInvalidMoveMessage(ApiWebsocketMessage apiMessage) {
log("invalid move message received, with move: ${apiMessage.move.toString()}");
ChessBloc.getInstance().add(
InvalidMovePlayed(
move: ChessMove.fromApiMove(apiMessage.move!),
squareInCheck: ChessCoordinate.fromApiCoordinate(
apiMessage.squareInCheck ?? const ApiCoordinate(col: 0, row: 0)),
),
);
2022-11-19 12:24:38 +00:00
}
void handleGameEndedMessage(ApiWebsocketMessage apiMessage) {
showDialog(
context: navigatorKey.currentContext!,
builder: (context) {
String msg = '';
if (apiMessage.reason == 'whiteIsCheckmated') {
msg = 'Black won! White is checkmated';
} else if (apiMessage.reason == 'blackIsCheckmated') {
msg = 'White won! Black is checkmated';
}
return AlertDialog(
title: const Text('Game ended'),
content: Text(msg),
actions: <Widget>[
TextButton(
child: const Text('Home'),
onPressed: () {
navigatorKey.currentContext!.goNamed('lobbySelector');
},
),
]);
},
);
}
}