WIP ws messages, TODO backend receiving frontend messages
This commit is contained in:
@@ -4,55 +4,6 @@ import 'dart:isolate';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:shared_models/room.dart';
|
||||
|
||||
// class GameRoomManager {
|
||||
// GameRoomManager({required SendPort this.socketManagerSendPort}) {
|
||||
// managerReceivePort = ReceivePort();
|
||||
// gamePorts = {};
|
||||
// receiveSubscription = managerReceivePort.listen((message) {
|
||||
// if (message is GameRoomManagerMessage) {
|
||||
// handleMessage(message);
|
||||
// } else if (message is GameRoomMessage) {
|
||||
// final gameUuid = message.gameUuid;
|
||||
// final gamePort = gamePorts[gameUuid];
|
||||
// if (gamePort == null) {
|
||||
// _logger.warning('Received GameRoomMessage for empty gamePort');
|
||||
// return;
|
||||
// }
|
||||
// gamePort.send(message);
|
||||
// } else {
|
||||
// _logger.warning('Received unknown message: $message');
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// late final Map<String, SendPort> gamePorts;
|
||||
// late final ReceivePort managerReceivePort;
|
||||
// late final StreamSubscription<dynamic> receiveSubscription;
|
||||
// final SendPort socketManagerSendPort;
|
||||
// final Logger _logger = Logger('GameRoomManager');
|
||||
|
||||
// void close() {
|
||||
// receiveSubscription.cancel();
|
||||
// //TODO remove connections
|
||||
// }
|
||||
|
||||
// Future<void> createRoom({required String roomUuid}) async {
|
||||
// // receivePort
|
||||
// final wsSendPort = SocketManager().createWsSendPort(roomUuid);
|
||||
// await Isolate.spawn(LiveGameRoom.spawn, LiveGameRoomData(roomUuid: roomUuid, wsSendPort: wsSendPort, gameManagerSendPort: ));
|
||||
// // first message from new isolate will be its SendPort
|
||||
// gamePorts[roomUuid] = await roomReceivePort.first as SendPort;
|
||||
// }
|
||||
|
||||
// void routePlayerToRoom(String roomCode, PlayerConnection player) {
|
||||
// gamePorts[roomCode]?.addPlayer(player);
|
||||
// }
|
||||
|
||||
// void handleMessage(message) {
|
||||
// throw UnimplementedError();
|
||||
// }
|
||||
// }
|
||||
|
||||
class LiveGameRoomData {
|
||||
LiveGameRoomData({
|
||||
required this.wsSendPort,
|
||||
@@ -102,15 +53,16 @@ class LiveGameRoom {
|
||||
}
|
||||
|
||||
void start() {
|
||||
gameLoop = Timer.periodic(const Duration(milliseconds: 750), update);
|
||||
gameLoop = Timer.periodic(const Duration(milliseconds: 3500), update);
|
||||
}
|
||||
|
||||
void update(Timer timer) {
|
||||
logger.finest('Room $roomUuid tick: ${timer.tick}');
|
||||
wsSendPort.send(
|
||||
RoomPingMessage(
|
||||
PingMessage.now(
|
||||
roomUuid,
|
||||
dest: PingDestination.client,
|
||||
userUuid: '',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ class SocketManager {
|
||||
final _connections = <String, Map<String, WebSocketChannel>>{};
|
||||
// Store isolate port and stream subscription to said port
|
||||
final _gameRoomSendPorts = <String, SendPort>{};
|
||||
final _gameRoomSpSubs = <String, StreamSubscription<dynamic>>{};
|
||||
final _gameRoomPortSubs = <String, StreamSubscription<dynamic>>{};
|
||||
final _gameRoomUserWsSubs = <String, StreamSubscription<dynamic>>{};
|
||||
|
||||
// Add a new connection
|
||||
Future<Status> addConnection(
|
||||
@@ -34,7 +35,7 @@ class SocketManager {
|
||||
required String userUuid,
|
||||
}) async {
|
||||
_logger.finer('Adding connection to socket manager for user $userUuid in room $roomUuid');
|
||||
if (!_gameRoomSpSubs.containsKey(roomUuid)) {
|
||||
if (!_gameRoomPortSubs.containsKey(roomUuid)) {
|
||||
final status = await spawnGameRoomIsolate(roomUuid);
|
||||
if (status == Status.failure) {
|
||||
return status;
|
||||
@@ -42,6 +43,11 @@ class SocketManager {
|
||||
}
|
||||
_connections.putIfAbsent(roomUuid, () => <String, WebSocketChannel>{});
|
||||
_connections[roomUuid]![userUuid] = connection;
|
||||
_logger.fine('Listening to websocket for messages');
|
||||
// ignore: cancel_subscriptions
|
||||
final sub = connection.stream.listen(_gameRoomMessageListener);
|
||||
_gameRoomUserWsSubs[userUuid] = sub;
|
||||
|
||||
return Status.success;
|
||||
}
|
||||
|
||||
@@ -67,6 +73,9 @@ class SocketManager {
|
||||
void broadcastToRoom(String roomUuid, GameRoomMessage message, {String? excludeUserUuid}) {
|
||||
_logger.fine('Broadcasting ${message.type} to room $roomUuid');
|
||||
_connections[roomUuid]?.forEach((userUuid, connection) {
|
||||
if (message is PingMessage) {
|
||||
message.userUuid = userUuid;
|
||||
}
|
||||
if (userUuid != excludeUserUuid) {
|
||||
connection.sink.add(jsonEncode(message.toJson()));
|
||||
}
|
||||
@@ -92,47 +101,49 @@ class SocketManager {
|
||||
final completer = Completer<SendPort>();
|
||||
|
||||
// ignore: cancel_subscriptions
|
||||
final sub = receivePort.listen((message) {
|
||||
// first message from new isolate will be its SendPort
|
||||
if (!completer.isCompleted) {
|
||||
completer.complete(message as SendPort);
|
||||
return;
|
||||
}
|
||||
if (message is GameRoomMessage) {
|
||||
switch (message) {
|
||||
case RoomPingMessage():
|
||||
if (message.dest != PingDestination.client) {
|
||||
_logger.warning('Got room ping meant for server');
|
||||
return;
|
||||
}
|
||||
broadcastToRoom(
|
||||
message.roomUuid,
|
||||
message,
|
||||
);
|
||||
final sub = receivePort.listen((message) => _gameRoomPortListener(message, completer));
|
||||
|
||||
case PlayerVoteMessage():
|
||||
// TODO: Handle this case.
|
||||
throw UnimplementedError();
|
||||
case PingMessage():
|
||||
// TODO: Handle this case.
|
||||
throw UnimplementedError();
|
||||
}
|
||||
} else {
|
||||
_logger.info('Unknown message: $message');
|
||||
}
|
||||
});
|
||||
_gameRoomSpSubs[roomUuid] = sub;
|
||||
_gameRoomPortSubs[roomUuid] = sub;
|
||||
_gameRoomSendPorts[roomUuid] = await completer.future;
|
||||
_logger.info('Spawned new game room $roomUuid, listening to messages from room.');
|
||||
|
||||
return Status.success;
|
||||
} catch (e) {
|
||||
_logger.severe('Failed to spawn game room isolate', e, StackTrace.current);
|
||||
_gameRoomSendPorts.remove(roomUuid);
|
||||
final sub = _gameRoomSpSubs.remove(roomUuid);
|
||||
final sub = _gameRoomPortSubs.remove(roomUuid);
|
||||
await sub?.cancel();
|
||||
}
|
||||
return Status.failure;
|
||||
}
|
||||
|
||||
void _gameRoomPortListener(dynamic message, Completer<SendPort> completer) {
|
||||
// first message from new isolate will be its SendPort
|
||||
if (!completer.isCompleted) {
|
||||
completer.complete(message as SendPort);
|
||||
return;
|
||||
}
|
||||
if (message is GameRoomMessage) {
|
||||
switch (message) {
|
||||
case PlayerVoteMessage():
|
||||
// TODO: Handle this case.
|
||||
throw UnimplementedError();
|
||||
case PingMessage():
|
||||
if (message.dest != PingDestination.client) {
|
||||
_logger.warning('Got room ping meant for server');
|
||||
return;
|
||||
}
|
||||
broadcastToRoom(
|
||||
message.roomUuid,
|
||||
message,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
_logger.info('Unknown message: $message');
|
||||
}
|
||||
}
|
||||
|
||||
void _gameRoomMessageListener(dynamic message) {}
|
||||
}
|
||||
|
||||
enum Status { success, failure }
|
||||
|
||||
@@ -16,17 +16,18 @@ Future<Response> onRequest(RequestContext context) async {
|
||||
try {
|
||||
// Parse the request body
|
||||
final body = await context.request.json();
|
||||
final createUserReq = CreateUserRequest.fromJson(body as Map<String, dynamic>);
|
||||
final joinRoomRequest = JoinRoomRequest.fromJson(body as Map<String, dynamic>);
|
||||
|
||||
// Generate token
|
||||
final authenticator = context.read<Authenticator>();
|
||||
final (token, user) = await authenticator.generateToken(createUserReq);
|
||||
final (token, user) = await authenticator.generateToken(joinRoomRequest);
|
||||
|
||||
if (token == null || user == null) {
|
||||
final body = CreateUserResponse(
|
||||
success: false,
|
||||
token: null,
|
||||
error: user == null ? 'Room ${createUserReq.roomCode} requested is not available' : 'Unexpected error occurred',
|
||||
error:
|
||||
user == null ? 'Room ${joinRoomRequest.roomCode} requested is not available' : 'Unexpected error occurred',
|
||||
uuid: null,
|
||||
).toJson();
|
||||
return Response.json(
|
||||
|
||||
@@ -10,7 +10,6 @@ Future<Response> onRequest(RequestContext context, String roomCode) async {
|
||||
|
||||
final handler = webSocketHandler(protocols: ['game.room.v1'], (channel, protocol) async {
|
||||
try {
|
||||
channel.sink.add('test');
|
||||
logger.finest(protocol);
|
||||
final room = await Db.getRoomByCode(roomCode);
|
||||
if (room == null) {
|
||||
|
||||
Reference in New Issue
Block a user