Introduce api types and some changes.
This commit is contained in:
parent
b0d6f4002c
commit
605743c0d2
32
lib/api/move.dart
Normal file
32
lib/api/move.dart
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
class ApiMove {
|
||||||
|
final ApiCoordinate startSquare;
|
||||||
|
final ApiCoordinate endSquare;
|
||||||
|
|
||||||
|
const ApiMove({
|
||||||
|
required this.startSquare,
|
||||||
|
required this.endSquare,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory ApiMove.fromJson(Map<String, dynamic> json) {
|
||||||
|
final startSquare = ApiCoordinate.fromJson(json['startSquare']);
|
||||||
|
final endSquare = ApiCoordinate.fromJson(json['endSquare']);
|
||||||
|
|
||||||
|
return ApiMove(startSquare: startSquare, endSquare: endSquare);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() =>
|
||||||
|
{'startSquare': startSquare, 'endSquare': endSquare};
|
||||||
|
}
|
||||||
|
|
||||||
|
class ApiCoordinate {
|
||||||
|
final int col;
|
||||||
|
final int row;
|
||||||
|
|
||||||
|
const ApiCoordinate({required this.col, required this.row});
|
||||||
|
|
||||||
|
factory ApiCoordinate.fromJson(Map<String, dynamic> json) {
|
||||||
|
return ApiCoordinate(col: json['col'], row: json['row']);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {'col': col, 'row': row};
|
||||||
|
}
|
30
lib/api/register.dart
Normal file
30
lib/api/register.dart
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
|
class ResponseFromRegisteringGame {
|
||||||
|
final UuidValue playerID;
|
||||||
|
final UuidValue lobbyID;
|
||||||
|
|
||||||
|
const ResponseFromRegisteringGame({
|
||||||
|
required this.playerID,
|
||||||
|
required this.lobbyID,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory ResponseFromRegisteringGame.fromJson(Map<String, dynamic> json) {
|
||||||
|
final playerid = UuidValue(json['playerID']);
|
||||||
|
final lobbyid = UuidValue(json['lobbyID']);
|
||||||
|
|
||||||
|
return ResponseFromRegisteringGame(playerID: playerid, lobbyID: lobbyid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WebsocketMessageIdentifyPlayer {
|
||||||
|
final String playerID;
|
||||||
|
final String lobbyID;
|
||||||
|
|
||||||
|
const WebsocketMessageIdentifyPlayer({
|
||||||
|
required this.playerID,
|
||||||
|
required this.lobbyID,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {'lobbyID': lobbyID, 'playerID': playerID};
|
||||||
|
}
|
@ -1,4 +1,7 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:mchess/api/move.dart';
|
||||||
import 'package:mchess/chess_bloc/chess_events.dart';
|
import 'package:mchess/chess_bloc/chess_events.dart';
|
||||||
import 'package:mchess/chess_bloc/chess_position.dart';
|
import 'package:mchess/chess_bloc/chess_position.dart';
|
||||||
import 'package:mchess/connection/ws_connection.dart';
|
import 'package:mchess/connection/ws_connection.dart';
|
||||||
@ -62,8 +65,13 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
|
|||||||
void ownMoveHandler(OwnPieceMoved event, Emitter<ChessBoardState> emit) {
|
void ownMoveHandler(OwnPieceMoved event, Emitter<ChessBoardState> emit) {
|
||||||
ChessPosition.getInstance().recordMove(event.startSquare, event.endSquare);
|
ChessPosition.getInstance().recordMove(event.startSquare, event.endSquare);
|
||||||
|
|
||||||
ServerConnection.getInstance().send(
|
var start = ApiCoordinate(
|
||||||
'mv ${event.startSquare.toString()} ${event.endSquare.toString()}');
|
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);
|
||||||
|
|
||||||
|
ServerConnection.getInstance().send(jsonEncode(move));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,10 @@ class ChessPosition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ChessPositionType get currentPosition => position;
|
ChessPositionType get currentPosition => position;
|
||||||
ChessMove get lastMove => history.last;
|
ChessMove? get lastMove {
|
||||||
|
if (history.isEmpty) return null;
|
||||||
|
return history.last;
|
||||||
|
}
|
||||||
|
|
||||||
void recordMove(ChessCoordinate from, ChessCoordinate to) {
|
void recordMove(ChessCoordinate from, ChessCoordinate to) {
|
||||||
position[to] = position[from] ?? const ChessPiece.none();
|
position[to] = position[from] ?? const ChessPiece.none();
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:mchess/api/move.dart';
|
||||||
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
||||||
import 'package:mchess/chess_bloc/chess_events.dart';
|
import 'package:mchess/chess_bloc/chess_events.dart';
|
||||||
import 'package:mchess/chess_bloc/chess_position.dart';
|
import 'package:mchess/chess_bloc/chess_position.dart';
|
||||||
|
import 'package:mchess/api/register.dart';
|
||||||
import 'package:mchess/utils/chess_utils.dart';
|
import 'package:mchess/utils/chess_utils.dart';
|
||||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||||
|
|
||||||
@ -31,7 +34,7 @@ class ServerConnection {
|
|||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void connect(String playerID) {
|
void connect(String playerID, lobbyID) {
|
||||||
if (wasConnected) channel.sink.close();
|
if (wasConnected) channel.sink.close();
|
||||||
|
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
@ -41,7 +44,8 @@ class ServerConnection {
|
|||||||
channel =
|
channel =
|
||||||
WebSocketChannel.connect(Uri.parse('wss://chess.sw-gross.de:8080'));
|
WebSocketChannel.connect(Uri.parse('wss://chess.sw-gross.de:8080'));
|
||||||
}
|
}
|
||||||
send(playerID);
|
send(jsonEncode(WebsocketMessageIdentifyPlayer(
|
||||||
|
playerID: (playerID), lobbyID: (lobbyID))));
|
||||||
|
|
||||||
log(channel.closeCode.toString());
|
log(channel.closeCode.toString());
|
||||||
|
|
||||||
@ -49,39 +53,27 @@ class ServerConnection {
|
|||||||
|
|
||||||
broadcast = channel.stream.asBroadcastStream();
|
broadcast = channel.stream.asBroadcastStream();
|
||||||
|
|
||||||
broadcast.listen((data) {
|
broadcast.listen(handleIncomingData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleIncomingData(dynamic data) {
|
||||||
log("Data received:");
|
log("Data received:");
|
||||||
log(data);
|
log(data);
|
||||||
|
var apiMove = ApiMove.fromJson(jsonDecode(data));
|
||||||
|
|
||||||
var receivedString = data.toString();
|
//Todo: Implement status messages
|
||||||
var splitString = receivedString.split(' ');
|
// e.g. to tell the client that both players connected, who is playing which color and so on
|
||||||
|
|
||||||
if (splitString[0] == "cl") {
|
var move = ChessMove.fromApiMove(apiMove);
|
||||||
ChessColor onBottom =
|
if (move == ChessPosition.getInstance().lastMove) {
|
||||||
splitString[1] == "white" ? ChessColor.white : ChessColor.black;
|
|
||||||
ChessBloc.getInstance().add(ColorDetermined(myColor: onBottom));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (splitString[0] == "bd") {
|
|
||||||
if (splitString[1] == "init") ChessBloc.getInstance().add(InitBoard());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (splitString[0] == ('mv')) {
|
|
||||||
var startSquare = ChessCoordinate.fromString(splitString[1]);
|
|
||||||
var endSquare = ChessCoordinate.fromString(splitString[2]);
|
|
||||||
if (ChessMove(from: startSquare, to: endSquare) ==
|
|
||||||
ChessPosition.getInstance().lastMove) {
|
|
||||||
//This is our own move that got resent by the server. Do not process.
|
//This is our own move that got resent by the server. Do not process.
|
||||||
} else {
|
} else {
|
||||||
log('lastMove: from: ${ChessPosition.getInstance().lastMove.from} to: ${ChessPosition.getInstance().lastMove.to}');
|
log('lastMove: from: ${ChessPosition.getInstance().lastMove?.from} to: ${ChessPosition.getInstance().lastMove?.to}');
|
||||||
log('constructed move: from: $startSquare to: $endSquare)}');
|
log('constructed move: from: ${move.from} to: ${move.to}');
|
||||||
log('Move received : ${startSquare.toAlphabetical()}:${endSquare.toAlphabetical()}');
|
log('Move received : ${move.from.toAlphabetical()}->${move.to.toAlphabetical()}');
|
||||||
|
|
||||||
ChessBloc.getInstance().add(OpponentPieceMoved(
|
ChessBloc.getInstance()
|
||||||
startSquare: startSquare, endSquare: endSquare));
|
.add(OpponentPieceMoved(startSquare: move.from, endSquare: move.to));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,8 @@ class ConnectionCubit extends Cubit<ConnectionCubitState> {
|
|||||||
return _instance;
|
return _instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void connect(String playerID) {
|
void connect(String playerID, lobbyID) {
|
||||||
ServerConnection.getInstance().connect(playerID);
|
ServerConnection.getInstance().connect(playerID, lobbyID);
|
||||||
emit(ConnectionCubitState(true));
|
emit(ConnectionCubitState(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
import 'package:uuid/uuid.dart';
|
|
||||||
|
|
||||||
class ResponseFromRegisteringGame {
|
|
||||||
final UuidValue playerID;
|
|
||||||
|
|
||||||
const ResponseFromRegisteringGame({
|
|
||||||
required this.playerID,
|
|
||||||
});
|
|
||||||
|
|
||||||
factory ResponseFromRegisteringGame.fromJson(Map<String, dynamic> json) {
|
|
||||||
final uuid = UuidValue(json['playerID']);
|
|
||||||
|
|
||||||
return ResponseFromRegisteringGame(
|
|
||||||
playerID: uuid,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,7 +14,8 @@ import 'package:uuid/uuid.dart';
|
|||||||
|
|
||||||
class ChessGame extends StatefulWidget {
|
class ChessGame extends StatefulWidget {
|
||||||
final UuidValue playerID;
|
final UuidValue playerID;
|
||||||
const ChessGame({required this.playerID, super.key});
|
final UuidValue lobbyID;
|
||||||
|
const ChessGame({required this.playerID, required this.lobbyID, super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ChessGame> createState() => _ChessGameState();
|
State<ChessGame> createState() => _ChessGameState();
|
||||||
@ -24,7 +25,8 @@ class _ChessGameState extends State<ChessGame> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
ConnectionCubit.getInstance().connect(widget.playerID.uuid);
|
ConnectionCubit.getInstance()
|
||||||
|
.connect(widget.playerID.uuid, widget.lobbyID.uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:mchess/models/models.dart';
|
import 'package:mchess/api/register.dart';
|
||||||
import 'package:mchess/pages/chess_game.dart';
|
import 'package:mchess/pages/chess_game.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
@ -18,6 +18,7 @@ class PrepareChessGameWidget extends StatelessWidget {
|
|||||||
log('future done ${snapshot.data?.playerID}');
|
log('future done ${snapshot.data?.playerID}');
|
||||||
return ChessGame(
|
return ChessGame(
|
||||||
playerID: snapshot.data!.playerID,
|
playerID: snapshot.data!.playerID,
|
||||||
|
lobbyID: snapshot.data!.lobbyID,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return const CircularProgressIndicator();
|
return const CircularProgressIndicator();
|
||||||
@ -26,8 +27,9 @@ class PrepareChessGameWidget extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<ResponseFromRegisteringGame> registerForRandomGame() async {
|
Future<ResponseFromRegisteringGame> registerForRandomGame() async {
|
||||||
final response =
|
final response = await http.get(
|
||||||
await http.get(Uri.parse('http://localhost:8080/api/random'));
|
Uri.parse('http://localhost:8080/api/random'),
|
||||||
|
headers: {"Accept": "application/json"});
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
log(response.body);
|
log(response.body);
|
||||||
@ -35,7 +37,7 @@ class PrepareChessGameWidget extends StatelessWidget {
|
|||||||
} else {
|
} else {
|
||||||
// If the server did not return a 200 OK response,
|
// If the server did not return a 200 OK response,
|
||||||
// then throw an exception.
|
// then throw an exception.
|
||||||
throw Exception('Failed to load album');
|
throw Exception('Failed to register for random game');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:mchess/api/move.dart';
|
||||||
import 'package:quiver/core.dart';
|
import 'package:quiver/core.dart';
|
||||||
|
|
||||||
enum ChessPieceName {
|
enum ChessPieceName {
|
||||||
@ -65,6 +66,10 @@ class ChessCoordinate {
|
|||||||
return ChessCoordinate(column, row);
|
return ChessCoordinate(column, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
factory ChessCoordinate.fromApiCoordinate(ApiCoordinate apiCoordinate) {
|
||||||
|
return ChessCoordinate(apiCoordinate.col, apiCoordinate.row);
|
||||||
|
}
|
||||||
|
|
||||||
ChessCoordinate.copyFrom(ChessCoordinate original)
|
ChessCoordinate.copyFrom(ChessCoordinate original)
|
||||||
: column = original.column,
|
: column = original.column,
|
||||||
row = original.row;
|
row = original.row;
|
||||||
@ -159,6 +164,13 @@ class ChessMove {
|
|||||||
|
|
||||||
ChessMove({required this.from, required this.to});
|
ChessMove({required this.from, required this.to});
|
||||||
|
|
||||||
|
factory ChessMove.fromApiMove(ApiMove apiMove) {
|
||||||
|
final start = ChessCoordinate.fromApiCoordinate(apiMove.startSquare);
|
||||||
|
final end = ChessCoordinate.fromApiCoordinate(apiMove.endSquare);
|
||||||
|
|
||||||
|
return ChessMove(from: start, to: end);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
operator ==(other) {
|
operator ==(other) {
|
||||||
return other is ChessMove && other.from == from && other.to == to;
|
return other is ChessMove && other.from == from && other.to == to;
|
||||||
|
Loading…
Reference in New Issue
Block a user