init
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../core/network/ws_client.dart';
|
||||
import 'game_models.dart';
|
||||
|
||||
class GameUiState extends Equatable {
|
||||
final WsStatus connection;
|
||||
final GameState? state;
|
||||
final HandResult? handResult; // اوورلی نتیجهی هَند (گذرا)
|
||||
final GameOver? gameOver; // اوورلی پایان بازی
|
||||
final String? notice; // پیام گذرا (خطا/خروج بازیکن)
|
||||
|
||||
const GameUiState({
|
||||
this.connection = WsStatus.connecting,
|
||||
this.state,
|
||||
this.handResult,
|
||||
this.gameOver,
|
||||
this.notice,
|
||||
});
|
||||
|
||||
GameUiState copyWith({
|
||||
WsStatus? connection,
|
||||
GameState? state,
|
||||
HandResult? handResult,
|
||||
GameOver? gameOver,
|
||||
String? notice,
|
||||
bool clearHandResult = false,
|
||||
bool clearNotice = false,
|
||||
}) =>
|
||||
GameUiState(
|
||||
connection: connection ?? this.connection,
|
||||
state: state ?? this.state,
|
||||
handResult: clearHandResult ? null : (handResult ?? this.handResult),
|
||||
gameOver: gameOver ?? this.gameOver,
|
||||
notice: clearNotice ? null : (notice ?? this.notice),
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [connection, state, handResult, gameOver, notice];
|
||||
}
|
||||
|
||||
class GameCubit extends Cubit<GameUiState> {
|
||||
final WsClient _ws;
|
||||
final String tier;
|
||||
late final StreamSubscription _msgSub;
|
||||
late final StreamSubscription _statusSub;
|
||||
|
||||
GameCubit(this._ws, this.tier) : super(const GameUiState()) {
|
||||
_msgSub = _ws.messages.listen(_onMessage);
|
||||
_statusSub = _ws.status.listen(_onStatus);
|
||||
_ws.connect();
|
||||
}
|
||||
|
||||
void _onStatus(WsStatus s) {
|
||||
emit(state.copyWith(connection: s));
|
||||
// پس از برقراری اتصال، درخواست ورود به صف؛ در صورت reconnect سرور خودش
|
||||
// بازیکن را به میز برمیگرداند (این پیام را نادیده میگیرد).
|
||||
if (s == WsStatus.connected) {
|
||||
_ws.send({'type': 'join_queue', 'tier': tier});
|
||||
}
|
||||
}
|
||||
|
||||
void _onMessage(Map<String, dynamic> msg) {
|
||||
switch (msg['type']) {
|
||||
case 'state':
|
||||
final gs = GameState.fromJson(msg);
|
||||
// با شروع دست/هَند جدید، اوورلی نتیجه پاک میشود.
|
||||
final clear = gs.phase == 'choose_trump' || gs.phase == 'playing';
|
||||
emit(state.copyWith(state: gs, clearHandResult: clear));
|
||||
case 'hand_over':
|
||||
emit(state.copyWith(handResult: HandResult.fromJson(msg)));
|
||||
case 'game_over':
|
||||
emit(state.copyWith(gameOver: GameOver.fromJson(msg)));
|
||||
case 'player_disconnected':
|
||||
emit(state.copyWith(notice: 'یک بازیکن قطع شد'));
|
||||
case 'player_reconnected':
|
||||
emit(state.copyWith(notice: 'بازیکن بازگشت'));
|
||||
case 'player_left':
|
||||
emit(state.copyWith(notice: 'یک بازیکن میز را ترک کرد'));
|
||||
case 'error':
|
||||
emit(state.copyWith(notice: (msg['message'] ?? 'خطا').toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void chooseTrump(String suit) => _ws.send({'type': 'choose_trump', 'suit': suit});
|
||||
|
||||
void playCard(String card) => _ws.send({'type': 'play_card', 'card': card});
|
||||
|
||||
void leave() => _ws.send({'type': 'leave'});
|
||||
|
||||
void clearNotice() => emit(state.copyWith(clearNotice: true));
|
||||
|
||||
@override
|
||||
Future<void> close() {
|
||||
_msgSub.cancel();
|
||||
_statusSub.cancel();
|
||||
_ws.dispose();
|
||||
return super.close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user