diff --git a/lib/api/websocket_message.dart b/lib/api/websocket_message.dart index 19cfd2c..23f559b 100644 --- a/lib/api/websocket_message.dart +++ b/lib/api/websocket_message.dart @@ -2,6 +2,7 @@ import 'package:mchess/api/move.dart'; enum MessageType { move, + invalidMove, colorDetermined; String toJson() => name; @@ -20,9 +21,13 @@ class ApiWebsocketMessage { final MessageType type; final ApiMove? move; final ApiColor? color; + final String? reason; ApiWebsocketMessage( - {required this.type, required this.move, required this.color}); + {required this.type, + required this.move, + required this.color, + required this.reason}); factory ApiWebsocketMessage.fromJson(Map json) { final type = MessageType.fromJson(json['messageType']); @@ -30,11 +35,25 @@ class ApiWebsocketMessage { switch (type) { case MessageType.colorDetermined: ret = ApiWebsocketMessage( - type: type, move: null, color: ApiColor.fromJson(json['color'])); + type: type, + move: null, + color: ApiColor.fromJson(json['color']), + reason: null); break; case MessageType.move: ret = ApiWebsocketMessage( - type: type, move: ApiMove.fromJson(json['move']), color: null); + type: type, + move: ApiMove.fromJson(json['move']), + color: null, + reason: null); + break; + case MessageType.invalidMove: + ret = ApiWebsocketMessage( + type: type, + move: ApiMove.fromJson(json['move']), + color: null, + reason: json['reason'], + ); } return ret; } diff --git a/lib/chess/chess_app.dart b/lib/chess/chess_app.dart index c1dacdd..fa0260c 100644 --- a/lib/chess/chess_app.dart +++ b/lib/chess/chess_app.dart @@ -18,7 +18,7 @@ class ChessApp extends StatelessWidget { useMaterial3: true, ), routerConfig: ChessAppRouter.getInstance().router, - title: 'mChess v0.1.1337', + title: 'mChess', ), ), ); diff --git a/lib/chess_bloc/chess_bloc.dart b/lib/chess_bloc/chess_bloc.dart index cdc45b0..fc459e5 100644 --- a/lib/chess_bloc/chess_bloc.dart +++ b/lib/chess_bloc/chess_bloc.dart @@ -21,8 +21,9 @@ class ChessBloc extends Bloc { ChessBloc._internal() : super(ChessBoardState.init()) { on(initBoard); on(flipBoard); - on(opponentMoveHandler); + on(moveHandler); on(ownMoveHandler); + on(invalidMoveHandler); } factory ChessBloc.getInstance() { @@ -45,8 +46,7 @@ class ChessBloc extends Bloc { emit(ChessBoardState(event.myColor, state.newTurnColor, state.position)); } - void opponentMoveHandler( - OpponentPieceMoved event, Emitter emit) { + void moveHandler(ReceivedMove event, Emitter emit) { log('opponentMoveHandler()'); ChessPosition.getInstance().recordMove(event.startSquare, event.endSquare); var newPosition = ChessPosition.getInstance().currentPosition; @@ -66,32 +66,37 @@ class ChessBloc extends Bloc { void ownMoveHandler(OwnPieceMoved event, Emitter emit) { log('ownMoveHandler()'); - ChessPosition.getInstance().recordMove(event.startSquare, event.endSquare); var start = ApiCoordinate( col: event.startSquare.column, row: event.startSquare.row); var end = ApiCoordinate(col: event.endSquare.column, row: event.endSquare.row); - var move = ApiMove(startSquare: start, endSquare: end); - var message = - ApiWebsocketMessage(type: MessageType.move, move: move, color: null); + var apiMove = ApiMove(startSquare: start, endSquare: end); + var apiMessage = ApiWebsocketMessage( + type: MessageType.move, move: apiMove, color: null, reason: null); - ServerConnection.getInstance().send(jsonEncode(message)); + ServerConnection.getInstance().send(jsonEncode(apiMessage)); - turnColor = state.newTurnColor == ChessColor.white - ? ChessColor.black - : ChessColor.white; - - var newPosition = ChessPosition.getInstance().currentPosition; + //Temporary chess position until server responds with acknoledgement + var move = ChessMove.fromApiMove(apiMove); + var tempPosition = ChessPosition.getInstance().copyOfCurrentPosition; + tempPosition[move.to] = tempPosition[move.from] ?? const ChessPiece.none(); + tempPosition[move.from] = const ChessPiece.none(); emit( ChessBoardState( state.bottomColor, turnColor, - newPosition, + tempPosition, ), ); } + + void invalidMoveHandler( + InvalidMovePlayed event, Emitter emit) { + emit(ChessBoardState(state.bottomColor, turnColor, + ChessPosition.getInstance().currentPosition)); + } } class ChessBoardState { diff --git a/lib/chess_bloc/chess_events.dart b/lib/chess_bloc/chess_events.dart index a7becb1..171c4e1 100644 --- a/lib/chess_bloc/chess_events.dart +++ b/lib/chess_bloc/chess_events.dart @@ -2,11 +2,11 @@ import 'package:mchess/utils/chess_utils.dart'; abstract class ChessEvent {} -class OpponentPieceMoved extends ChessEvent { +class ReceivedMove extends ChessEvent { final ChessCoordinate startSquare; final ChessCoordinate endSquare; - OpponentPieceMoved({required this.startSquare, required this.endSquare}); + ReceivedMove({required this.startSquare, required this.endSquare}); } class OwnPieceMoved extends ChessEvent { @@ -25,3 +25,9 @@ class ColorDetermined extends ChessEvent { ColorDetermined({required this.myColor}); } + +class InvalidMovePlayed extends ChessEvent { + final ChessMove move; + + InvalidMovePlayed({required this.move}); +} diff --git a/lib/chess_bloc/chess_position.dart b/lib/chess_bloc/chess_position.dart index 2133a04..aaa3065 100644 --- a/lib/chess_bloc/chess_position.dart +++ b/lib/chess_bloc/chess_position.dart @@ -20,6 +20,7 @@ class ChessPosition { } ChessPositionType get currentPosition => position; + ChessPositionType get copyOfCurrentPosition => Map.from(position); ChessMove? get lastMove { if (history.isEmpty) return null; return history.last; @@ -103,7 +104,7 @@ class ChessPosition { logString = '$logString\n'; } - log(logString); + print(logString); } void logHistory(ChessMoveHistory hist) { diff --git a/lib/connection/ws_connection.dart b/lib/connection/ws_connection.dart index d129aa3..92690a6 100644 --- a/lib/connection/ws_connection.dart +++ b/lib/connection/ws_connection.dart @@ -69,6 +69,9 @@ class ServerConnection { case MessageType.move: handleIncomingMoveMessage(apiMessage); break; + + case MessageType.invalidMove: + handleInvalidMoveMessage(apiMessage); } } @@ -79,11 +82,13 @@ class ServerConnection { void handleIncomingMoveMessage(ApiWebsocketMessage apiMessage) { var move = ChessMove.fromApiMove(apiMessage.move!); - if (move == ChessPosition.getInstance().lastMove) { - //This is our own move that got resent by the server. Do not process. - } else { - ChessBloc.getInstance() - .add(OpponentPieceMoved(startSquare: move.from, endSquare: move.to)); - } + 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!))); } } diff --git a/pubspec.lock b/pubspec.lock index 9c0d7d9..7aa76cc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -144,14 +144,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" - js: - dependency: transitive - description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.dev" - source: hosted - version: "0.6.7" lints: dependency: transitive description: @@ -341,6 +333,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" web_socket_channel: dependency: "direct main" description: @@ -358,5 +358,5 @@ packages: source: hosted version: "6.3.0" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.1.0-185.0.dev <4.0.0" flutter: ">=3.7.0-0" diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png deleted file mode 100644 index b749bfe..0000000 Binary files a/web/icons/Icon-192.png and /dev/null differ diff --git a/web/index.html b/web/index.html index 4bca956..1f6d9d5 100644 --- a/web/index.html +++ b/web/index.html @@ -24,7 +24,7 @@ - + @@ -40,20 +40,85 @@ - + + + +
+ + Loading indicator... +
+ diff --git a/web/manifest.json b/web/manifest.json index 082697a..cffd6a6 100644 --- a/web/manifest.json +++ b/web/manifest.json @@ -10,23 +10,23 @@ "prefer_related_applications": false, "icons": [ { - "src": "icons/Icon-192.png", + "src": "web_icons/Icon-192.png", "sizes": "192x192", "type": "image/png" }, { - "src": "icons/Icon-512.png", + "src": "web_icons/Icon-512.png", "sizes": "512x512", "type": "image/png" }, { - "src": "icons/Icon-maskable-192.png", + "src": "web_icons/Icon-maskable-192.png", "sizes": "192x192", "type": "image/png", "purpose": "maskable" }, { - "src": "icons/Icon-maskable-512.png", + "src": "web_icons/Icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" diff --git a/web/web_icons/Icon-192.png b/web/web_icons/Icon-192.png new file mode 100644 index 0000000..2dc8e53 Binary files /dev/null and b/web/web_icons/Icon-192.png differ diff --git a/web/icons/Icon-512.png b/web/web_icons/Icon-512.png similarity index 100% rename from web/icons/Icon-512.png rename to web/web_icons/Icon-512.png diff --git a/web/icons/Icon-maskable-192.png b/web/web_icons/Icon-maskable-192.png similarity index 100% rename from web/icons/Icon-maskable-192.png rename to web/web_icons/Icon-maskable-192.png diff --git a/web/icons/Icon-maskable-512.png b/web/web_icons/Icon-maskable-512.png similarity index 100% rename from web/icons/Icon-maskable-512.png rename to web/web_icons/Icon-maskable-512.png