using System.Collections.Generic; using System.Linq; using System.Threading; using Cysharp.Threading.Tasks; using Game.Player; using UnityEngine; namespace Game.Room { public interface IRoomManager { IRoom currentRoom { get; } IRoom CreateRoom(RoomType roomType, string location); void SetCurrentRoom(RoomType roomType); IRoom GetRoom(RoomType roomType); IRoom GetRandomRoom(); RandomRoomData GetAllRandomRoom(); UniTask JoinRoomAsync(RoomType roomType, IPlayer player, CancellationToken token); bool QuitRoom(RoomType roomType, IPlayer player); UniTask QuitAllRoomAsync(CancellationToken token); void DeleteRoom(RoomType roomType); void DeleteAllRoom(); } public class RoomManager : ManagerBase, IRoomManager { private IRoom birthRoom; private Dictionary _rooms = new Dictionary(); private Dictionary tmp = new Dictionary(); private IRoom _currentRoom; public IRoom currentRoom => this._currentRoom; protected override void OnInit() { base.OnInit(); EventManager.Instance.Subscribe(RoomJinBeiChangeEventArgs.EventId, RoomJinBeiChangeEvent); } protected override void OnDispose() { base.OnDispose(); EventManager.Instance.Unsubscribe(RoomJinBeiChangeEventArgs.EventId, RoomJinBeiChangeEvent); this.DeleteAllRoom(); } private void RoomJinBeiChangeEvent(object sender, GameEventArgs e) { var args = e as RoomJinBeiChangeEventArgs; args.room.InvestmentJinBei(args.player, args.jinBei); } public IRoom CreateRoom(RoomType roomType, string location) { if (this._rooms.TryGetValue(roomType, out var room)) return room; var gameObject = Game.resourceManager.LoadGameObjectSync(location); room = new Room(roomType, gameObject); this._rooms.Add(roomType, room); return room; } public void SetCurrentRoom(RoomType roomType) { if (roomType == RoomType.出生点) return; if (this._rooms.TryGetValue(roomType, out var room)) this._currentRoom = room; } public IRoom GetRoom(RoomType roomType) { return this._rooms.GetValueOrDefault(roomType); } public IRoom GetRandomRoom() { int index = Random.Range(1, this._rooms.Count); return this._rooms[(RoomType)index]; } public RandomRoomData GetAllRandomRoom() { if (this.tmp.Count <= 0 || this.tmp.ContainsKey(RoomType.出生点)) { this.tmp = new Dictionary(this._rooms); this.tmp.Remove(RoomType.出生点); } // kill var killRoom = this.tmp.Values.ToList(); ShuffleAndRemoveRooms(killRoom); // var survivorRoom = this.tmp.Values.ToList().Except(killRoom).ToList(); // 标记一下 foreach (var room in killRoom) { room.SetIsCanReturnJinBei(false); } // 标记一下 foreach (var room in survivorRoom) { room.SetIsCanReturnJinBei(true); } RandomRoomData roomData = new RandomRoomData(); roomData.killRoom = killRoom; roomData.survivorRoom = survivorRoom; return roomData; } public void ShuffleAndRemoveRooms(List list) { ShuffleList(list); int removeCount = Random.Range(1, list.Count); for (int i = 0; i < removeCount; i++) { list.RemoveAt(list.Count - 1); } } // 实现Fisher-Yates洗牌算法 private void ShuffleList(List list) { for (int i = list.Count - 1; i > 0; i--) { int swapIndex = Random.Range(0, i + 1); (list[i], list[swapIndex]) = (list[swapIndex], list[i]); } } public async UniTask JoinRoomAsync(RoomType roomType, IPlayer player, CancellationToken token) { if (player.isMoving) return false; foreach (IRoom roomsValue in this._rooms.Values) { var roomInfo = roomsValue.roomInfo; if (player.roleType == RoleType.Player) roomInfo.SetSelect(false); } if (this._rooms.TryGetValue(roomType, out var room)) { if (player.roleType == RoleType.Player) room.roomInfo.SetSelect(true); await room.JoinAsync(player, token); return true; } return false; } public bool QuitRoom(RoomType roomType, IPlayer player) { if (this._rooms.TryGetValue(roomType, out var room)) { room.Quit(player); return true; } return false; } public async UniTask QuitAllRoomAsync(CancellationToken token) { List tasks = new List(); foreach (IRoom room in this.tmp.Values) { var players = room.QuitAndClearAll(); foreach (var player in players) { // Debug.Log($"正在安排{player}返回出生点"); var task = this.JoinRoomAsync(RoomType.出生点, player, token); tasks.Add(task); } } await UniTask.WhenAll(tasks); // Debug.Log("全部返回了出生点"); } public void DeleteRoom(RoomType roomType) { if (this._rooms.TryGetValue(roomType, out var room)) room.Dispose(); } public void DeleteAllRoom() { foreach (var room in this._rooms.Values) room.Dispose(); this._rooms.Clear(); } } public struct RandomRoomData { public IReadOnlyList killRoom; public IReadOnlyList survivorRoom; } }