using Dominion.NET_WPF.Caching; using DominionBase; using DominionBase.Cards; using DominionBase.Enums; using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Xml.Serialization; namespace Dominion.NET_WPF { public class SettingsChangedEventArgs : EventArgs { } public enum ToolTipShowDuration { Off = 0, Short = 2000, Normal = 5000, Long = 10000, SuperLong = 20000 } public enum LayoutStyle { [DisplayString(ResourceKey = "LayoutStyle_Supply2Columns")] [Description("2 columns of supply piles")] Supply2Columns, [DisplayString(ResourceKey = "LayoutStyle_Supply4Columns")] [Description("4 columns of supply piles")] Supply4Columns } public enum GameLogLocation { [DisplayString(ResourceKey = "GameLogLocation_InCommonArea")] [Description("In common area")] InCommonArea, [DisplayString(ResourceKey = "GameLogLocation_InGameTabArea")] [Description("In game tab area")] InGameTabArea } [AttributeUsage(AttributeTargets.Field)] public sealed class DisplayStringAttribute : Attribute { public string Value { get; } public string ResourceKey { get; set; } public DisplayStringAttribute(string v) { Value = v; } public DisplayStringAttribute() { } } [Serializable] public class PlayerSettings { private string _aiClass = string.Empty; private Type _aiClassType; private Color _uiColor = Colors.Transparent; private string _backgroundBrushString = string.Empty; private Brush _backgroundBrush = Brushes.Transparent; public string Name { get; set; } = string.Empty; public string AIClass { get { return _aiClass; } set { _aiClass = value; _aiClassType = DominionBase.Players.PlayerCollection.GetAllAIs().FirstOrDefault(t => t.FullName == value); } } [XmlIgnore] public Type AIClassType { get { return _aiClassType; } set { _aiClassType = value; _aiClass = value.FullName; } } public Color UIColor { get { return _uiColor; } set { _uiColor = new Color { R = value.R, G = value.G, B = value.B, A = value.A }; } } public string BackgroundBrushString { get { return _backgroundBrushString; } set { _backgroundBrushString = value; ForegroundBrush = Brushes.Black; if (value == string.Empty) _backgroundBrush = Brushes.Transparent; else if (Uri.IsWellFormedUriString(value, UriKind.RelativeOrAbsolute) || File.Exists(value)) { BitmapImage imageBitmap; imageBitmap = ImageRepository.LoadImage(value); //try { imageBitmap = ImageRepository.LoadImage(value); } //catch { return; } _backgroundBrush = new ImageBrush(imageBitmap); var ir = ImageRepository.Acquire(); ForegroundBrush = ir.GetForegroundBrush(imageBitmap); ImageRepository.Release(); } else { var bc = new BrushConverter(); _backgroundBrush = (Brush)bc.ConvertFromString(value); } } } [XmlIgnore] public Brush BackgroundBrush { get { return _backgroundBrush; } set { var bc = new BrushConverter(); _backgroundBrush = value; ForegroundBrush = Brushes.Black; if ((value as ImageBrush)?.ImageSource is BitmapImage) { var imageSource = ((ImageBrush)value).ImageSource; var imageBitmap = (BitmapImage)imageSource; _backgroundBrushString = imageBitmap.SourcePath(); var ir = ImageRepository.Acquire(); ForegroundBrush = ir.GetForegroundBrush(imageBitmap); ImageRepository.Release(); } else _backgroundBrushString = bc.ConvertToString(value); } } [XmlIgnore] public Brush ForegroundBrush { get; set; } = Brushes.Black; } [Serializable] public class PlayerSettingsCollection : List { } [Serializable] public class Settings { public delegate void SettingsChangedEventHandler(object sender, SettingsChangedEventArgs e); public virtual event SettingsChangedEventHandler SettingsChanged; private int _numberOfPlayers = 2; private int _numberOfHumanPlayers = 1; private string _backgroundBrushString = string.Empty; private Brush _backgroundBrush = Brushes.Transparent; private Size _windowSize; private PresetCollection _presets; public Settings() { } public Settings(Settings settings) { CopyFrom(settings); } public int NumberOfPlayers { get { return _numberOfPlayers; } set { _numberOfPlayers = value; if (_numberOfPlayers < 1) _numberOfPlayers = 1; if (_numberOfPlayers > 6) _numberOfPlayers = 6; if (NumberOfHumanPlayers > _numberOfPlayers) NumberOfHumanPlayers = _numberOfPlayers; } } public int NumberOfHumanPlayers { get { return _numberOfHumanPlayers; } set { _numberOfHumanPlayers = value; if (_numberOfHumanPlayers < 0) _numberOfHumanPlayers = 0; if (_numberOfHumanPlayers > NumberOfPlayers) _numberOfHumanPlayers = NumberOfPlayers; } } public bool IdenticalStartingHands { get; set; } public bool PromptUnplayedActions { get; set; } = true; public bool PromptUnspentBuysTreasure { get; set; } = true; public bool PromptUnspentBuysTreasureOnlyNotCopperCurseRuins { get; set; } = true; public bool NeverBuyCopperOrCurseExceptWhenGoonsIsInPlay { get; set; } public bool ChooserAutomaticallyClickWhenSatisfied { get; set; } = true; public bool ChooserAutomaticallyRevealMoat { get; set; } public bool ChooserAutomaticallyRevealProvince { get; set; } public bool ChooserAutomaticallyMoveStashToTop { get; set; } [XmlArray] public PlayerSettingsCollection PlayerSettings { get; set; } = new PlayerSettingsCollection(); [XmlArray] public CardsSettingsCollection CardSettings { get; set; } = new CardsSettingsCollection(); [XmlArray] public ConstraintCollection Constraints { get; set; } = new ConstraintCollection(10); public ConstraintCollection LandscapeCardConstraints { get; set; } = new ConstraintCollection(3); public ToolTipShowDuration ToolTipShowDuration { get; set; } = ToolTipShowDuration.Normal; public bool ShowToolTipOnRightClick { get; set; } public bool DisplaySupplyPileNames { get; set; } = true; public bool DisplayBasicSupplyPileNames { get; set; } = true; public LayoutStyle LayoutStyle { get; set; } = LayoutStyle.Supply2Columns; public GameLogLocation GameLogLocation { get; set; } = GameLogLocation.InCommonArea; public string BackgroundBrushString { get { return _backgroundBrushString; } set { _backgroundBrushString = value; ForegroundBrush = Brushes.Black; if (value == string.Empty) _backgroundBrush = Brushes.Transparent; else if (Uri.IsWellFormedUriString(value, UriKind.RelativeOrAbsolute) || File.Exists(value)) { BitmapImage imageBitmap; imageBitmap = ImageRepository.LoadImage(value); //try { imageBitmap = ImageRepository.LoadImage(value); } //catch { return; } _backgroundBrush = new ImageBrush(imageBitmap); var ir = ImageRepository.Acquire(); ForegroundBrush = ir.GetForegroundBrush(imageBitmap); ImageRepository.Release(); //PixelColor[,] pixels = ImageUtilities.GetPixels(imageBitmap); //double l_sum = 0; //for (int x = 0; x < pixels.GetLength(0); x++) //{ // for (int y = 0; y < pixels.GetLength(1); y++) // { // Color c = Color.FromArgb(pixels[x, y].Alpha, pixels[x, y].Red, pixels[x, y].Green, pixels[x, y].Blue); // double l = 0.2126 * c.ScR + 0.7152 * c.ScG + 0.0722 * c.ScB; // l_sum += l; // } //} //l_sum /= pixels.GetLength(0) * pixels.GetLength(1); //if (l_sum < 0.5) // this.ForegroundBrush = Brushes.White; } else { var bc = new BrushConverter(); _backgroundBrush = (Brush)bc.ConvertFromString(value); } } } [XmlIgnore] public Brush BackgroundBrush { get { return _backgroundBrush; } set { var bc = new BrushConverter(); _backgroundBrush = value; ForegroundBrush = Brushes.Black; if ((value as ImageBrush)?.ImageSource is BitmapImage) { var imageSource = ((ImageBrush)value).ImageSource; var imageBitmap = (BitmapImage)imageSource; _backgroundBrushString = imageBitmap.SourcePath(); var ir = ImageRepository.Acquire(); ForegroundBrush = ir.GetForegroundBrush(imageBitmap); ImageRepository.Release(); //PixelColor[,] pixels = ImageUtilities.GetPixels(imageBitmap); //double l_sum = 0; //for (int x = 0; x < pixels.GetLength(0); x++) //{ // for (int y = 0; y < pixels.GetLength(1); y++) // { // Color c = Color.FromArgb(pixels[x, y].Alpha, pixels[x, y].Red, pixels[x, y].Green, pixels[x, y].Blue); // double l = 0.2126 * c.ScR + 0.7152 * c.ScG + 0.0722 * c.ScB; // l_sum += l; // } //} //l_sum /= pixels.GetLength(0) * pixels.GetLength(1); //if (l_sum < 0.5) // this.ForegroundBrush = Brushes.White; } else _backgroundBrushString = bc.ConvertToString(value); } } [XmlIgnore] public Brush ForegroundBrush { get; set; } = Brushes.Black; public bool AutoCollapseOldTurns { get; set; } public bool DisplayVictoryPoints { get; set; } public bool UseCustomImages { get; set; } public string CustomImagesPathSmall { get; set; } = "small"; public string CustomImagesPathMedium { get; set; } = "medium"; public bool UseCustomToolTips { get; set; } public string CustomToolTipsPath { get; set; } = string.Empty; public string CustomBackgroundPath { get; set; } = "background"; public Size WindowSize { get { return _windowSize; } set { _windowSize = value; } } public WindowState WindowState { get; set; } = WindowState.Normal; public DateTime LastUpdateCheck { get; set; } = DateTime.MinValue; public bool UpdateAvailable { get; set; } #region Presets [XmlIgnore] public PresetCollection Presets { get { return _presets ?? (_presets = PresetCollection.Parse()); } private set { _presets = value; } } public bool UsePreset { get; set; } public bool SettingsShowPresetCards { get; set; } = true; public string PresetName { get; set; } = string.Empty; #endregion #region Auto-Play Treasures public bool AutoPlayTreasures { get; set; } public bool AutoPlayTreasuresIncludingLoan { get; set; } = true; public bool AutoPlayTreasuresLoanFirst { get; set; } = true; public bool AutoPlayTreasuresIncludingHornOfPlenty { get; set; } = true; public bool AutoPlayTreasuresHornOfPlentyFirst { get; set; } = true; #endregion public bool RandomAIUnique { get; set; } [XmlArray] public List RandomAIAllowedAIs { get; set; } = new List(); public bool AutomaticallyAcceptKingdomCards { get; set; } public ColonyPlatinumUsage ColonyPlatinumUsage { get; set; } = ColonyPlatinumUsage.FirstKingdomCard; public bool ForceColonyPlatinum { get; set; } public ShelterUsage ShelterUsage { get; set; } = ShelterUsage.LastKingdomCard; public bool ForceShelters { get; set; } public LandscapeCardUsage LandscapeCardUsage { get; set; } = LandscapeCardUsage.Percentage; public EditionUsage EditionUsage { get; set; } = EditionUsage.SecondPriority; //public EditionUsage EditionUsage { get; set; } = EditionUsage.Errata2019Priority; public AISpeed AISpeed { get; set; } = AISpeed.Medium; private static string Filename => Path.Combine(DominionBase.Utilities.Application.ApplicationPath, "settings.xml"); private static string OldFilename => Path.Combine(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName), "settings.xml"); private static List GetAllSerializingTypes(IEnumerable cards) { var typeDict = new List() { typeof(Cost), typeof(Traits) }; foreach (var card in cards) typeDict.AddRange(card.GetSerializingTypes()); return typeDict; } public void UnloadImages() { BackgroundBrushString = ""; foreach (var setting in PlayerSettings) setting.BackgroundBrushString = ""; } public void Save() { var copy = SettingsChanged; copy?.Invoke(this, new SettingsChangedEventArgs()); try { var allCards = CardCollection.GetAllCards(c => true, EditionUsage.AllowDuplicates); var xsSettings = new XmlSerializer(typeof(Settings), GetAllSerializingTypes(allCards).ToArray()); var swSettings = new StreamWriter(Filename); xsSettings.Serialize(swSettings, this); swSettings.Close(); } catch (IOException) { } } public static Settings Load() { var allCards = CardCollection.GetAllCards(c => true, EditionUsage.AllowDuplicates); Settings settings; var allCardsList = allCards as IList ?? allCards.ToList(); try { var mySerializer = new XmlSerializer(typeof(Settings), GetAllSerializingTypes(allCardsList).ToArray()); // This should only need to be here temporarily -- probably 3-5 releases -- until all the other versions get transitioned to the new saving area var filename = Filename; if (!File.Exists(Filename)) filename = OldFilename; using (var myFileStream = new FileStream(filename, FileMode.Open)) { settings = (Settings)mySerializer.Deserialize(myFileStream); } } catch { settings = new Settings(); } while (settings.PlayerSettings.Count < 6) settings.PlayerSettings.Add(new PlayerSettings() { Name = $"Player {settings.PlayerSettings.Count + 1}", AIClassType = typeof(DominionBase.Players.AI.Standard), UIColor = HlsColor.HlsToRgb(24*settings.PlayerSettings.Count*2, 0.85, 1, 1) }); // Go through each card to make sure that the card's default settings are defined foreach (var card in allCardsList) { var csc = card.GenerateSettings(); if (csc.Count == 0) // This card has no custom settings, so we can skip it continue; if (!settings.CardSettings.ContainsKey(card.Name)) settings.CardSettings[card.Name] = new CardsSettings(card.Name); var cardSettings = settings.CardSettings[card.Name]; // Go through each setting defined for the card & make sure it exists foreach (var cSetting in csc) { var key = cSetting.GetType(); if (!cardSettings.CardSettingCollection.ContainsKey(key)) cardSettings.CardSettingCollection[key] = cSetting; } card.FinalizeSettings(cardSettings.CardSettingCollection); } return settings; } internal void CopyFrom(Settings settings) { NumberOfPlayers = settings.NumberOfPlayers; NumberOfHumanPlayers = settings.NumberOfHumanPlayers; IdenticalStartingHands = settings.IdenticalStartingHands; PromptUnplayedActions = settings.PromptUnplayedActions; PromptUnspentBuysTreasure = settings.PromptUnspentBuysTreasure; PromptUnspentBuysTreasureOnlyNotCopperCurseRuins = settings.PromptUnspentBuysTreasureOnlyNotCopperCurseRuins; NeverBuyCopperOrCurseExceptWhenGoonsIsInPlay = settings.NeverBuyCopperOrCurseExceptWhenGoonsIsInPlay; DisplaySupplyPileNames = settings.DisplaySupplyPileNames; DisplayBasicSupplyPileNames = settings.DisplayBasicSupplyPileNames; ChooserAutomaticallyClickWhenSatisfied = settings.ChooserAutomaticallyClickWhenSatisfied; ShowToolTipOnRightClick = settings.ShowToolTipOnRightClick; ChooserAutomaticallyRevealMoat = settings.ChooserAutomaticallyRevealMoat; ChooserAutomaticallyRevealProvince = settings.ChooserAutomaticallyRevealProvince; ChooserAutomaticallyMoveStashToTop = settings.ChooserAutomaticallyMoveStashToTop; PlayerSettings = settings.PlayerSettings; CardSettings = settings.CardSettings.DeepClone(); Constraints = new ConstraintCollection(10); foreach (var constraint in settings.Constraints) Constraints.Add(new Constraint(constraint.ConstraintType, constraint.ConstraintValue, constraint.Minimum, constraint.Maximum)); LandscapeCardConstraints = new ConstraintCollection(3); foreach (var constraint in settings.LandscapeCardConstraints) LandscapeCardConstraints.Add(new Constraint(constraint.ConstraintType, constraint.ConstraintValue, constraint.Minimum, constraint.Maximum)); ToolTipShowDuration = settings.ToolTipShowDuration; LayoutStyle = settings.LayoutStyle; GameLogLocation = settings.GameLogLocation; BackgroundBrush = settings.BackgroundBrush; AutoCollapseOldTurns = settings.AutoCollapseOldTurns; DisplayVictoryPoints = settings.DisplayVictoryPoints; UseCustomImages = settings.UseCustomImages; CustomImagesPathSmall = settings.CustomImagesPathSmall; CustomImagesPathMedium = settings.CustomImagesPathMedium; UseCustomToolTips = settings.UseCustomToolTips; CustomToolTipsPath = settings.CustomToolTipsPath; CustomBackgroundPath = settings.CustomBackgroundPath; WindowSize = settings.WindowSize; WindowState = settings.WindowState; LastUpdateCheck = settings.LastUpdateCheck; UpdateAvailable = settings.UpdateAvailable; Presets = settings.Presets; UsePreset = settings.UsePreset; SettingsShowPresetCards = settings.SettingsShowPresetCards; PresetName = settings.PresetName; AutoPlayTreasures = settings.AutoPlayTreasures; AutoPlayTreasuresIncludingLoan = settings.AutoPlayTreasuresIncludingLoan; AutoPlayTreasuresLoanFirst = settings.AutoPlayTreasuresLoanFirst; AutoPlayTreasuresIncludingHornOfPlenty = settings.AutoPlayTreasuresIncludingHornOfPlenty; AutoPlayTreasuresHornOfPlentyFirst = settings.AutoPlayTreasuresHornOfPlentyFirst; RandomAIUnique = settings.RandomAIUnique; RandomAIAllowedAIs = new List(settings.RandomAIAllowedAIs); AutomaticallyAcceptKingdomCards = settings.AutomaticallyAcceptKingdomCards; ColonyPlatinumUsage = settings.ColonyPlatinumUsage; ForceColonyPlatinum = settings.ForceColonyPlatinum; ShelterUsage = settings.ShelterUsage; ForceShelters = settings.ForceShelters; LandscapeCardUsage = settings.LandscapeCardUsage; EditionUsage = settings.EditionUsage; AISpeed = settings.AISpeed; } } }