#region Copyright & License Information /* * Copyright 2007-2022 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. For more * information, see COPYING. */ #endregion using System; using System.Collections.Generic; namespace OpenRA.Primitives { /// /// Provides a mapping of players to values, as well as fast lookup by player index. /// public readonly struct PlayerDictionary : IReadOnlyList, IReadOnlyDictionary where T : class { readonly T[] valueByPlayerIndex; readonly Dictionary valueByPlayer; public PlayerDictionary(World world, Func valueFactory) { var players = world.Players; if (players.Length == 0) throw new InvalidOperationException("The players in the world have not yet been set."); // The world players never change, so we can safely maintain an array of values. // We need to enforce T is a class, so if it changes that change is available in both collections. valueByPlayerIndex = new T[players.Length]; valueByPlayer = new Dictionary(players.Length); for (var i = 0; i < players.Length; i++) { var player = players[i]; var state = valueFactory(player, i); valueByPlayerIndex[i] = state; valueByPlayer[player] = state; } } public PlayerDictionary(World world, Func valueFactory) : this(world, (player, _) => valueFactory(player)) { } /// Gets the value for the specified player. This is slower than specifying a player index. public T this[Player player] => valueByPlayer[player]; /// Gets the value for the specified player index. public T this[int playerIndex] => valueByPlayerIndex[playerIndex]; public int Count => valueByPlayerIndex.Length; public IEnumerable Keys => ((IReadOnlyDictionary)valueByPlayer).Keys; public IEnumerable Values => ((IReadOnlyDictionary)valueByPlayer).Values; public IEnumerator GetEnumerator() { return ((IEnumerable)valueByPlayerIndex).GetEnumerator(); } bool IReadOnlyDictionary.ContainsKey(Player key) { return valueByPlayer.ContainsKey(key); } bool IReadOnlyDictionary.TryGetValue(Player key, out T value) { return valueByPlayer.TryGetValue(key, out value); } IEnumerator> IEnumerable>.GetEnumerator() { return valueByPlayer.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } } }