ReboundEmulator/Core/Rooms/RoomManager.cs
Moonbase 2631d3199c Implement Multiplayer Support
Implement Custom Screen Name Support
2026-10-06 19:00:15 -07:00

48 lines
2.5 KiB
C#

using NotPogo.Core.Rooms.GameRooms;
using System.Collections.Concurrent;
using System.Reflection;
namespace NotPogo.Core.Rooms
{
public static class RoomManager
{
static readonly ConcurrentDictionary<string, Room> Rooms = new();
static readonly Dictionary<string, Func<string, IGameRoom>> Factories = BuildFactories();
static Dictionary<string, Func<string, IGameRoom>> BuildFactories()
{
var map = new Dictionary<string, Func<string, IGameRoom>>(StringComparer.OrdinalIgnoreCase);
foreach (var type in typeof(IGameRoom).Assembly.GetTypes()
.Where(t => typeof(IGameRoom).IsAssignableFrom(t) && !t.IsAbstract))
{
foreach (var attr in type.GetCustomAttributes<GameRoomAttribute>())
{
// constructor convention: (string ruleId) if the game has modes, otherwise parameterless
Func<string, IGameRoom> factory =
type.GetConstructor([typeof(string)]) is not null ? rule => (IGameRoom)Activator.CreateInstance(type, rule)!
: type.GetConstructor(Type.EmptyTypes) is not null ? _ => (IGameRoom)Activator.CreateInstance(type)!
: throw new InvalidOperationException($"{type.Name} needs a (string ruleId) or parameterless constructor");
if (!map.TryAdd(attr.GameCode, factory))
throw new InvalidOperationException($"Game code '{attr.GameCode}' is claimed by more than one room class");
}
}
return map;
}
static IGameRoom CreateGame(string gameCode, string ruleId) =>
Factories.TryGetValue(gameCode, out var create) ? create(ruleId) : new ChatOnlyRoom();
public static Room Define(string key, string humanName, string gameCode, string ruleId, bool isLive, int softCapacity = 50, int tabId = 1) =>
Rooms.GetOrAdd(key, _ => new Room(key, humanName, gameCode, ruleId, softCapacity, tabId, isLive, CreateGame(gameCode, ruleId)));
public static Room GetOrCreate(string key, string gameCode, string ruleId = "") =>
Rooms.GetOrAdd(key, _ => new Room(key, key, gameCode, ruleId, 50, 1, false, CreateGame(gameCode, ruleId)));
public static Room? Find(string key) => Rooms.TryGetValue(key, out var r) ? r : null;
public static IEnumerable<Room> ForGame(string gameCode) => Rooms.Values.Where(r => r.GameCode == gameCode);
}
}