A lot of changes again?!?
This commit is contained in:
parent
43fca47dae
commit
52540ec96c
@ -1,30 +1,43 @@
|
|||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
class ResponseFromRegisteringGame {
|
class PlayerInfo {
|
||||||
final UuidValue playerID;
|
final UuidValue? playerID;
|
||||||
final UuidValue lobbyID;
|
final UuidValue? lobbyID;
|
||||||
|
final String? passphrase;
|
||||||
|
|
||||||
const ResponseFromRegisteringGame({
|
const PlayerInfo({
|
||||||
required this.playerID,
|
required this.playerID,
|
||||||
required this.lobbyID,
|
required this.lobbyID,
|
||||||
|
required this.passphrase,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory ResponseFromRegisteringGame.fromJson(Map<String, dynamic> json) {
|
factory PlayerInfo.fromJson(Map<String, dynamic> json) {
|
||||||
final playerid = UuidValue(json['playerID']);
|
final playerid = UuidValue(json['playerID']);
|
||||||
final lobbyid = UuidValue(json['lobbyID']);
|
final lobbyid = UuidValue(json['lobbyID']);
|
||||||
|
final passphrase = json['passphrase'];
|
||||||
|
|
||||||
return ResponseFromRegisteringGame(playerID: playerid, lobbyID: lobbyid);
|
return PlayerInfo(
|
||||||
|
playerID: playerid, lobbyID: lobbyid, passphrase: passphrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
'playerID': playerID,
|
||||||
|
'lobbyID': lobbyID,
|
||||||
|
'passphrase': passphrase,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class WebsocketMessageIdentifyPlayer {
|
class WebsocketMessageIdentifyPlayer {
|
||||||
final String playerID;
|
final String playerID;
|
||||||
final String lobbyID;
|
final String lobbyID;
|
||||||
|
final String? passphrase;
|
||||||
|
|
||||||
const WebsocketMessageIdentifyPlayer({
|
const WebsocketMessageIdentifyPlayer({
|
||||||
required this.playerID,
|
required this.playerID,
|
||||||
required this.lobbyID,
|
required this.lobbyID,
|
||||||
|
required this.passphrase,
|
||||||
});
|
});
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {'lobbyID': lobbyID, 'playerID': playerID};
|
Map<String, dynamic> toJson() =>
|
||||||
|
{'lobbyID': lobbyID, 'playerID': playerID, 'passphrase': passphrase};
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
|
|||||||
|
|
||||||
ServerConnection.getInstance().send(jsonEncode(apiMessage));
|
ServerConnection.getInstance().send(jsonEncode(apiMessage));
|
||||||
|
|
||||||
//Temporary chess position until server responds with acknoledgement
|
//Temporary chess position until server responds with acknowledgement
|
||||||
var move = ChessMove.fromApiMove(apiMove);
|
var move = ChessMove.fromApiMove(apiMove);
|
||||||
var tempPosition = ChessPosition.getInstance().copyOfCurrentPosition;
|
var tempPosition = ChessPosition.getInstance().copyOfCurrentPosition;
|
||||||
tempPosition[move.to] = tempPosition[move.from] ?? const ChessPiece.none();
|
tempPosition[move.to] = tempPosition[move.from] ?? const ChessPiece.none();
|
||||||
|
@ -104,7 +104,7 @@ class ChessPosition {
|
|||||||
logString = '$logString\n';
|
logString = '$logString\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
print(logString);
|
log(logString);
|
||||||
}
|
}
|
||||||
|
|
||||||
void logHistory(ChessMoveHistory hist) {
|
void logHistory(ChessMoveHistory hist) {
|
||||||
|
@ -4,8 +4,8 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:mchess/api/websocket_message.dart';
|
import 'package:mchess/api/websocket_message.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/api/register.dart';
|
import 'package:mchess/api/register.dart';
|
||||||
|
import 'package:mchess/connection_cubit/connection_cubit.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';
|
||||||
|
|
||||||
@ -34,9 +34,7 @@ class ServerConnection {
|
|||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void connect(String playerID, lobbyID) {
|
void connect(String playerID, lobbyID, String? passphrase) {
|
||||||
if (wasConnected) channel.sink.close();
|
|
||||||
|
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
channel =
|
channel =
|
||||||
WebSocketChannel.connect(Uri.parse('ws://localhost:8080/api/ws'));
|
WebSocketChannel.connect(Uri.parse('ws://localhost:8080/api/ws'));
|
||||||
@ -44,15 +42,18 @@ class ServerConnection {
|
|||||||
channel = WebSocketChannel.connect(
|
channel = WebSocketChannel.connect(
|
||||||
Uri.parse('wss://chess.sw-gross.de:9999/api/ws'));
|
Uri.parse('wss://chess.sw-gross.de:9999/api/ws'));
|
||||||
}
|
}
|
||||||
send(jsonEncode(WebsocketMessageIdentifyPlayer(
|
send(
|
||||||
playerID: (playerID), lobbyID: (lobbyID))));
|
jsonEncode(
|
||||||
|
WebsocketMessageIdentifyPlayer(
|
||||||
|
playerID: (playerID),
|
||||||
|
lobbyID: (lobbyID),
|
||||||
|
passphrase: (passphrase),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
log(channel.closeCode.toString());
|
log(channel.closeCode.toString());
|
||||||
|
|
||||||
wasConnected = true;
|
|
||||||
|
|
||||||
broadcast = channel.stream.asBroadcastStream();
|
broadcast = channel.stream.asBroadcastStream();
|
||||||
|
|
||||||
broadcast.listen(handleIncomingData);
|
broadcast.listen(handleIncomingData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,6 +79,7 @@ class ServerConnection {
|
|||||||
void handleIncomingColorDeterminedMessage(ApiWebsocketMessage apiMessage) {
|
void handleIncomingColorDeterminedMessage(ApiWebsocketMessage apiMessage) {
|
||||||
ChessBloc.getInstance().add(
|
ChessBloc.getInstance().add(
|
||||||
ColorDetermined(myColor: ChessColor.fromApiColor(apiMessage.color!)));
|
ColorDetermined(myColor: ChessColor.fromApiColor(apiMessage.color!)));
|
||||||
|
ConnectionCubit.getInstance().opponentConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleIncomingMoveMessage(ApiWebsocketMessage apiMessage) {
|
void handleIncomingMoveMessage(ApiWebsocketMessage apiMessage) {
|
||||||
|
@ -15,16 +15,19 @@ class ConnectionCubit extends Cubit<ConnectionCubitState> {
|
|||||||
return _instance;
|
return _instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void connect(String playerID, lobbyID) {
|
void connect(String playerID, lobbyID, String? passphrase) {
|
||||||
ServerConnection.getInstance().connect(playerID, lobbyID);
|
ServerConnection.getInstance().connect(playerID, lobbyID, passphrase);
|
||||||
|
}
|
||||||
|
|
||||||
|
void opponentConnected() {
|
||||||
emit(ConnectionCubitState(true));
|
emit(ConnectionCubitState(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConnectionCubitState {
|
class ConnectionCubitState {
|
||||||
final bool reconnecting;
|
final bool opponentConnected;
|
||||||
|
|
||||||
ConnectionCubitState(this.reconnecting);
|
ConnectionCubitState(this.opponentConnected);
|
||||||
|
|
||||||
factory ConnectionCubitState.init() {
|
factory ConnectionCubitState.init() {
|
||||||
return ConnectionCubitState(false);
|
return ConnectionCubitState(false);
|
||||||
|
@ -6,16 +6,18 @@ import 'package:mchess/chess_bloc/chess_bloc.dart';
|
|||||||
|
|
||||||
import 'package:mchess/chess/chess_board.dart';
|
import 'package:mchess/chess/chess_board.dart';
|
||||||
import 'package:mchess/chess/turn_indicator_widget.dart';
|
import 'package:mchess/chess/turn_indicator_widget.dart';
|
||||||
import 'package:mchess/connection_cubit/connection_cubit.dart';
|
|
||||||
|
|
||||||
import 'package:mchess/connection/ws_connection.dart';
|
|
||||||
import 'package:mchess/utils/widgets/server_log_widget.dart';
|
import 'package:mchess/utils/widgets/server_log_widget.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
class ChessGame extends StatefulWidget {
|
class ChessGame extends StatefulWidget {
|
||||||
final UuidValue playerID;
|
final UuidValue playerID;
|
||||||
final UuidValue lobbyID;
|
final UuidValue lobbyID;
|
||||||
const ChessGame({required this.playerID, required this.lobbyID, super.key});
|
final String? passphrase;
|
||||||
|
const ChessGame(
|
||||||
|
{required this.playerID,
|
||||||
|
required this.lobbyID,
|
||||||
|
required this.passphrase,
|
||||||
|
super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ChessGame> createState() => _ChessGameState();
|
State<ChessGame> createState() => _ChessGameState();
|
||||||
@ -25,28 +27,16 @@ class _ChessGameState extends State<ChessGame> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
ConnectionCubit.getInstance()
|
|
||||||
.connect(widget.playerID.uuid, widget.lobbyID.uuid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Center(
|
body: FittedBox(
|
||||||
child: FittedBox(
|
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
if (kDebugMode)
|
if (kDebugMode) const ServerLogWidget(textColor: Colors.white),
|
||||||
StreamBuilder(
|
|
||||||
stream: ServerConnection.getInstance().broadcast,
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
return ServerLogWidget(
|
|
||||||
snapshot.data ?? "<snapshot empty>",
|
|
||||||
textColor: Colors.white,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Container(
|
Container(
|
||||||
margin: const EdgeInsets.all(20),
|
margin: const EdgeInsets.all(20),
|
||||||
child: BlocBuilder<ChessBloc, ChessBoardState>(
|
child: BlocBuilder<ChessBloc, ChessBoardState>(
|
||||||
@ -61,13 +51,24 @@ class _ChessGameState extends State<ChessGame> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.goNamed('lobbySelector');
|
context.push('/');
|
||||||
},
|
},
|
||||||
child: const Icon(Icons.arrow_back),
|
child: const Icon(Icons.cancel),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ChessGameArguments {
|
||||||
|
final UuidValue lobbyID;
|
||||||
|
final UuidValue playerID;
|
||||||
|
final String? passphrase;
|
||||||
|
|
||||||
|
ChessGameArguments({
|
||||||
|
required this.lobbyID,
|
||||||
|
required this.playerID,
|
||||||
|
required this.passphrase,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
144
lib/pages/host_game.dart
Normal file
144
lib/pages/host_game.dart
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:mchess/api/register.dart';
|
||||||
|
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
||||||
|
import 'package:mchess/chess_bloc/chess_events.dart';
|
||||||
|
import 'package:mchess/connection_cubit/connection_cubit.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:mchess/pages/chess_game.dart';
|
||||||
|
|
||||||
|
class HostGameWidget extends StatefulWidget {
|
||||||
|
const HostGameWidget({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<HostGameWidget> createState() => _HostGameWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HostGameWidgetState extends State<HostGameWidget> {
|
||||||
|
late Future<PlayerInfo?> registerResponse;
|
||||||
|
late ChessGameArguments chessGameArgs;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
ChessBloc.getInstance().add(InitBoard());
|
||||||
|
|
||||||
|
registerResponse = hostPrivateGame();
|
||||||
|
connectToWebsocket(registerResponse);
|
||||||
|
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void connectToWebsocket(Future<PlayerInfo?> resp) {
|
||||||
|
resp.then((value) {
|
||||||
|
if (value == null) return;
|
||||||
|
|
||||||
|
chessGameArgs = ChessGameArguments(
|
||||||
|
lobbyID: value.lobbyID!,
|
||||||
|
playerID: value.playerID!,
|
||||||
|
passphrase: value.passphrase);
|
||||||
|
|
||||||
|
ConnectionCubit.getInstance().connect(
|
||||||
|
value.playerID!.uuid,
|
||||||
|
value.lobbyID!.uuid,
|
||||||
|
value.passphrase,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: FutureBuilder<PlayerInfo?>(
|
||||||
|
future: registerResponse,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState != ConnectionState.done) {
|
||||||
|
return const SizedBox(
|
||||||
|
height: 100,
|
||||||
|
width: 100,
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
String passphrase = snapshot.data?.passphrase ?? "no passphrase";
|
||||||
|
return BlocListener<ConnectionCubit, ConnectionCubitState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
// We wait for our opponent to connect
|
||||||
|
if (state.opponentConnected) {
|
||||||
|
context.push('/game', extra: chessGameArgs);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Give this phrase to your friend and sit tight:',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.primary),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 25),
|
||||||
|
Text(
|
||||||
|
passphrase,
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 25),
|
||||||
|
const CircularProgressIndicator()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
child: const Icon(Icons.cancel),
|
||||||
|
onPressed: () {
|
||||||
|
context.push('/');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<PlayerInfo?> hostPrivateGame() async {
|
||||||
|
String addr;
|
||||||
|
Response response;
|
||||||
|
|
||||||
|
if (kDebugMode) {
|
||||||
|
addr = 'http://localhost:8080/api/hostPrivate';
|
||||||
|
} else {
|
||||||
|
addr = 'https://chess.sw-gross.de:9999/api/hostPrivate';
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
response = await http
|
||||||
|
.get(Uri.parse(addr), headers: {"Accept": "application/json"});
|
||||||
|
} catch (e) {
|
||||||
|
log(e.toString());
|
||||||
|
|
||||||
|
if (!context.mounted) return null;
|
||||||
|
|
||||||
|
const snackBar = SnackBar(
|
||||||
|
backgroundColor: Colors.amberAccent,
|
||||||
|
content: Text("mChess server is not responding. Try again or give up"),
|
||||||
|
);
|
||||||
|
Future.delayed(const Duration(seconds: 2), () {
|
||||||
|
ScaffoldMessenger.of(context).clearSnackBars();
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||||
|
context.pop();
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
log(response.body);
|
||||||
|
return PlayerInfo.fromJson(jsonDecode(response.body));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
118
lib/pages/join_game.dart
Normal file
118
lib/pages/join_game.dart
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:mchess/api/register.dart';
|
||||||
|
import 'package:mchess/connection_cubit/connection_cubit.dart';
|
||||||
|
import 'package:mchess/pages/chess_game.dart';
|
||||||
|
|
||||||
|
class JoinGameWidget extends StatefulWidget {
|
||||||
|
const JoinGameWidget({
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<JoinGameWidget> createState() => _JoinGameWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _JoinGameWidgetState extends State<JoinGameWidget> {
|
||||||
|
final myController = TextEditingController();
|
||||||
|
late Future<PlayerInfo?> joinGameFuture;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: TextField(
|
||||||
|
controller: myController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'Enter passphrase here',
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
joinGameFuture = joinPrivateGame();
|
||||||
|
switchToGame(joinGameFuture);
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.check),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
onPressed: () {
|
||||||
|
context.push('/');
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.cancel),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void switchToGame(Future<PlayerInfo?> resp) {
|
||||||
|
resp.then((value) {
|
||||||
|
if (value == null) return;
|
||||||
|
|
||||||
|
var chessGameArgs = ChessGameArguments(
|
||||||
|
lobbyID: value.lobbyID!,
|
||||||
|
playerID: value.playerID!,
|
||||||
|
passphrase: value.passphrase);
|
||||||
|
|
||||||
|
ConnectionCubit.getInstance().connect(
|
||||||
|
value.playerID!.uuid,
|
||||||
|
value.lobbyID!.uuid,
|
||||||
|
value.passphrase,
|
||||||
|
);
|
||||||
|
|
||||||
|
context.push('/game', extra: chessGameArgs);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<PlayerInfo?> joinPrivateGame() async {
|
||||||
|
String addr;
|
||||||
|
Response response;
|
||||||
|
|
||||||
|
// server expects us to send the passphrase
|
||||||
|
var info = PlayerInfo(
|
||||||
|
playerID: null, lobbyID: null, passphrase: myController.text);
|
||||||
|
|
||||||
|
if (kDebugMode) {
|
||||||
|
addr = 'http://localhost:8080/api/joinPrivate';
|
||||||
|
} else {
|
||||||
|
addr = 'https://chess.sw-gross.de:9999/api/joinPrivate';
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
response = await http.post(Uri.parse(addr),
|
||||||
|
body: jsonEncode(info), headers: {"Accept": "application/json"});
|
||||||
|
} catch (e) {
|
||||||
|
log(e.toString());
|
||||||
|
|
||||||
|
if (!context.mounted) return null;
|
||||||
|
|
||||||
|
const snackBar = SnackBar(
|
||||||
|
backgroundColor: Colors.amberAccent,
|
||||||
|
content: Text("mChess server is not responding. Try again or give up"),
|
||||||
|
);
|
||||||
|
Future.delayed(const Duration(seconds: 2), () {
|
||||||
|
ScaffoldMessenger.of(context).clearSnackBars();
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||||
|
context.pop();
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
var info = PlayerInfo.fromJson(jsonDecode(response.body));
|
||||||
|
log('Player info received from server: ');
|
||||||
|
log('lobbyID: ${info.lobbyID}');
|
||||||
|
log('playerID: ${info.playerID}');
|
||||||
|
log('passphrase: ${info.passphrase}');
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -4,17 +4,76 @@ import 'package:go_router/go_router.dart';
|
|||||||
class LobbySelector extends StatelessWidget {
|
class LobbySelector extends StatelessWidget {
|
||||||
const LobbySelector({super.key});
|
const LobbySelector({super.key});
|
||||||
|
|
||||||
|
final buttonStyle = const ButtonStyle();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Center(
|
body: Center(
|
||||||
child: TextButton(
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.goNamed('prepareChessGame');
|
context.push('/prepareRandom');
|
||||||
},
|
},
|
||||||
child: const Text('Random lobby'),
|
child: const Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Icon(Icons.question_mark),
|
||||||
|
SizedBox(
|
||||||
|
width: 10,
|
||||||
|
),
|
||||||
|
Text('Random')
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 25,
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
_dialogBuilder(context);
|
||||||
|
},
|
||||||
|
child: const Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Icon(Icons.lock),
|
||||||
|
SizedBox(
|
||||||
|
width: 10,
|
||||||
|
),
|
||||||
|
Text('Private')
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _dialogBuilder(BuildContext context) {
|
||||||
|
return showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('Host or join?'),
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
child: const Text('Host'),
|
||||||
|
onPressed: () {
|
||||||
|
context.push('/host');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: const Text('Join'),
|
||||||
|
onPressed: () {
|
||||||
|
context.push('/join');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
import 'dart:developer';
|
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:go_router/go_router.dart';
|
|
||||||
import 'package:http/http.dart';
|
|
||||||
import 'package:mchess/api/register.dart';
|
|
||||||
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
|
||||||
import 'package:mchess/chess_bloc/chess_events.dart';
|
|
||||||
import 'package:mchess/pages/chess_game.dart';
|
|
||||||
import 'package:http/http.dart' as http;
|
|
||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
class PrepareChessGameWidget extends StatefulWidget {
|
|
||||||
const PrepareChessGameWidget({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<PrepareChessGameWidget> createState() => _PrepareChessGameWidgetState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PrepareChessGameWidgetState extends State<PrepareChessGameWidget> {
|
|
||||||
late Future randomGameResponse;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
ChessBloc.getInstance().add(InitBoard());
|
|
||||||
randomGameResponse = registerForRandomGame();
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
body: FutureBuilder(
|
|
||||||
future: randomGameResponse,
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
|
||||||
log('Response from registering to random game ${snapshot.data}');
|
|
||||||
|
|
||||||
if (snapshot.data != null) {
|
|
||||||
return ChessGame(
|
|
||||||
playerID: snapshot.data!.playerID,
|
|
||||||
lobbyID: snapshot.data!.lobbyID,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return const Center(
|
|
||||||
child: SizedBox(
|
|
||||||
height: 100,
|
|
||||||
width: 100,
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<ResponseFromRegisteringGame?> registerForRandomGame() async {
|
|
||||||
String addr;
|
|
||||||
if (kDebugMode) {
|
|
||||||
addr = 'http://localhost:8080/api/random';
|
|
||||||
} else {
|
|
||||||
addr = 'https://chess.sw-gross.de:9999/api/random';
|
|
||||||
}
|
|
||||||
|
|
||||||
Response response;
|
|
||||||
|
|
||||||
try {
|
|
||||||
response = await http
|
|
||||||
.get(Uri.parse(addr), headers: {"Accept": "application/json"});
|
|
||||||
} catch (e) {
|
|
||||||
const snackBar = SnackBar(
|
|
||||||
backgroundColor: Colors.amberAccent,
|
|
||||||
content:
|
|
||||||
Text("mChess server is not responding. Try again or give up"));
|
|
||||||
|
|
||||||
if (!context.mounted) return null;
|
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).clearSnackBars();
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
|
||||||
|
|
||||||
Future.delayed(const Duration(seconds: 2), () {
|
|
||||||
context.goNamed('lobbySelector');
|
|
||||||
});
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
|
||||||
log(response.body);
|
|
||||||
return ResponseFromRegisteringGame.fromJson(jsonDecode(response.body));
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
97
lib/pages/prepare_random_game.dart
Normal file
97
lib/pages/prepare_random_game.dart
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:mchess/api/register.dart';
|
||||||
|
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
||||||
|
import 'package:mchess/chess_bloc/chess_events.dart';
|
||||||
|
import 'package:mchess/pages/chess_game.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
class PrepareRandomGameWidget extends StatefulWidget {
|
||||||
|
const PrepareRandomGameWidget({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<PrepareRandomGameWidget> createState() =>
|
||||||
|
_PrepareRandomGameWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PrepareRandomGameWidgetState extends State<PrepareRandomGameWidget> {
|
||||||
|
late Future randomGameResponse;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
ChessBloc.getInstance().add(InitBoard());
|
||||||
|
|
||||||
|
randomGameResponse = registerForRandomGame();
|
||||||
|
|
||||||
|
goToGameWhenResponseIsHere(randomGameResponse as Future<PlayerInfo?>);
|
||||||
|
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void goToGameWhenResponseIsHere(Future<PlayerInfo?> resp) {
|
||||||
|
resp.then((value) {
|
||||||
|
if (value == null) return;
|
||||||
|
context.push(
|
||||||
|
'/game',
|
||||||
|
extra: ChessGameArguments(
|
||||||
|
lobbyID: value.lobbyID!,
|
||||||
|
playerID: value.playerID!,
|
||||||
|
passphrase: value.passphrase),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: SizedBox(
|
||||||
|
height: 100,
|
||||||
|
width: 100,
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<PlayerInfo?> registerForRandomGame() async {
|
||||||
|
String addr;
|
||||||
|
Response response;
|
||||||
|
|
||||||
|
if (kDebugMode) {
|
||||||
|
addr = 'http://localhost:8080/api/random';
|
||||||
|
} else {
|
||||||
|
addr = 'https://chess.sw-gross.de:9999/api/random';
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
response = await http
|
||||||
|
.get(Uri.parse(addr), headers: {"Accept": "application/json"});
|
||||||
|
} catch (e) {
|
||||||
|
if (!context.mounted) return null;
|
||||||
|
|
||||||
|
const snackBar = SnackBar(
|
||||||
|
backgroundColor: Colors.amberAccent,
|
||||||
|
content: Text("mChess server is not responding. Try again or give up"),
|
||||||
|
);
|
||||||
|
Future.delayed(const Duration(seconds: 2), () {
|
||||||
|
ScaffoldMessenger.of(context).clearSnackBars();
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||||
|
context.pop();
|
||||||
|
});
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
log(response.body);
|
||||||
|
return PlayerInfo.fromJson(jsonDecode(response.body));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,9 @@
|
|||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:mchess/pages/chess_game.dart';
|
||||||
|
import 'package:mchess/pages/join_game.dart';
|
||||||
import 'package:mchess/pages/lobby_selector.dart';
|
import 'package:mchess/pages/lobby_selector.dart';
|
||||||
import 'package:mchess/pages/prepare_chess_game.dart';
|
import 'package:mchess/pages/host_game.dart';
|
||||||
|
import 'package:mchess/pages/prepare_random_game.dart';
|
||||||
|
|
||||||
class ChessAppRouter {
|
class ChessAppRouter {
|
||||||
static final ChessAppRouter _instance = ChessAppRouter._internal();
|
static final ChessAppRouter _instance = ChessAppRouter._internal();
|
||||||
@ -19,11 +22,36 @@ class ChessAppRouter {
|
|||||||
builder: (context, state) => const LobbySelector(),
|
builder: (context, state) => const LobbySelector(),
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/play',
|
path: '/prepareRandom',
|
||||||
name: 'prepareChessGame',
|
name: 'prepareRandom',
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return const PrepareChessGameWidget();
|
return const PrepareRandomGameWidget();
|
||||||
})
|
}),
|
||||||
|
GoRoute(
|
||||||
|
path: '/host',
|
||||||
|
name: 'host',
|
||||||
|
builder: (context, state) {
|
||||||
|
return const HostGameWidget();
|
||||||
|
}),
|
||||||
|
GoRoute(
|
||||||
|
path: '/join',
|
||||||
|
name: 'join',
|
||||||
|
builder: (context, state) {
|
||||||
|
return const JoinGameWidget();
|
||||||
|
}),
|
||||||
|
GoRoute(
|
||||||
|
path: '/game',
|
||||||
|
name: 'game',
|
||||||
|
builder: (context, state) {
|
||||||
|
var args = state.extra as ChessGameArguments;
|
||||||
|
|
||||||
|
return ChessGame(
|
||||||
|
lobbyID: args.lobbyID,
|
||||||
|
playerID: args.playerID,
|
||||||
|
passphrase: args.passphrase,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:mchess/connection/ws_connection.dart';
|
||||||
|
|
||||||
class ServerLogWidget extends StatefulWidget {
|
class ServerLogWidget extends StatefulWidget {
|
||||||
final Color textColor;
|
final Color textColor;
|
||||||
final String addString;
|
|
||||||
|
|
||||||
const ServerLogWidget(this.addString, {required this.textColor, super.key});
|
const ServerLogWidget({required this.textColor, super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() => ServerLogWidgetState();
|
State<StatefulWidget> createState() => ServerLogWidgetState();
|
||||||
@ -17,17 +17,11 @@ class ServerLogWidgetState extends State<ServerLogWidget> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
log.add(widget.addString);
|
// return Container();
|
||||||
return SizedBox(
|
return StreamBuilder(
|
||||||
height: 200,
|
stream: ServerConnection.getInstance().broadcast,
|
||||||
width: 200,
|
builder: (context, snapshot) {
|
||||||
child: ListView(
|
return Container();
|
||||||
children: [
|
});
|
||||||
for (int i = 0; i < log.length; i++)
|
|
||||||
Text(
|
|
||||||
style: TextStyle(color: widget.textColor, fontSize: 20), log[i])
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@ void main() {
|
|||||||
// Build our app and trigger a frame.
|
// Build our app and trigger a frame.
|
||||||
await tester.pumpWidget(ChessGame(
|
await tester.pumpWidget(ChessGame(
|
||||||
playerID: UuidValue("test"),
|
playerID: UuidValue("test"),
|
||||||
|
lobbyID: UuidValue("testLobbyId"),
|
||||||
|
passphrase: 'test',
|
||||||
));
|
));
|
||||||
|
|
||||||
// Verify that our counter starts at 0.
|
// Verify that our counter starts at 0.
|
||||||
|
Loading…
Reference in New Issue
Block a user