// // Licensed under the MIT License. See LICENSE file in the project root for full license information. // namespace MUnique.OpenMU.ChatServer; using System.Collections.Concurrent; using Microsoft.Extensions.Logging; /// /// The Chat Room Manager manages the creation and destruction of chat rooms. /// internal class ChatRoomManager { private readonly ILoggerFactory _loggerFactory; /// /// All currently used chat rooms. /// private readonly IDictionary _rooms = new ConcurrentDictionary(); private readonly ConcurrentBag _freeRoomIds = new(); /// /// Initializes a new instance of the class. /// /// The logger factory. public ChatRoomManager(ILoggerFactory loggerFactory) { this._loggerFactory = loggerFactory; for (ushort i = 0; i < ushort.MaxValue; ++i) { this._freeRoomIds.Add(i); } } /// /// Gets the opened rooms. /// public ICollection OpenedRooms => this._rooms.Values; /// /// Creates a new ChatRoom and returns its Room-ID. /// /// The Room-ID of the new room. Returns ushort.MaxValue, if there is no free chat room available. public ushort CreateChatRoom() { if (!this._freeRoomIds.TryTake(out ushort roomId)) { throw new InvalidOperationException("There is no free room id, so the chat room couldn't be created."); } var room = new ChatRoom(roomId, this._loggerFactory.CreateLogger()); room.RoomClosed += this.OnChatRoomClosed; this._rooms.Add(roomId, room); return roomId; } /// /// Returns the chat room with the corresponding Room-ID. /// Returns null, if ChatRoom wasn't found. /// /// Room-ID. /// ChatRoom or null. internal ChatRoom? GetChatRoom(ushort roomId) { this._rooms.TryGetValue(roomId, out var room); return room; } private void OnChatRoomClosed(object? sender, ChatRoomClosedEventArgs eventArgs) { var room = eventArgs.ChatRoom; this._rooms.Remove(room.RoomId); this._freeRoomIds.Add(room.RoomId); room.Dispose(); } }