From af45ac1e2ddff1e510f343b35b58e381eba3bc97 Mon Sep 17 00:00:00 2001 From: JustArchi Date: Fri, 21 Oct 2016 20:32:22 +0200 Subject: [PATCH] Implement TradingPreferences, closes #351 It also kills deprecated now SteamTradeMatcher bool property --- ArchiSteamFarm/BotConfig.cs | 14 +- ArchiSteamFarm/Trading.cs | 6 +- ArchiSteamFarm/config/example.json | 2 +- ConfigGenerator/BotConfig.cs | 16 ++- ConfigGenerator/ConfigGenerator.csproj | 3 + ConfigGenerator/FlagEnumEditor.cs | 192 +++++++++++++++++++++++++ 6 files changed, 222 insertions(+), 11 deletions(-) create mode 100644 ConfigGenerator/FlagEnumEditor.cs diff --git a/ArchiSteamFarm/BotConfig.cs b/ArchiSteamFarm/BotConfig.cs index 8490f2ec6..f4a0c6bac 100644 --- a/ArchiSteamFarm/BotConfig.cs +++ b/ArchiSteamFarm/BotConfig.cs @@ -47,6 +47,14 @@ namespace ArchiSteamFarm { NamesDescending } + [Flags] + internal enum ETradingPreferences : byte { + [SuppressMessage("ReSharper", "UnusedMember.Global")] + None = 0, + AcceptDonations = 1, + SteamTradeMatcher = 2 + } + [JsonProperty(Required = Required.DisallowNull)] internal readonly bool Enabled = false; @@ -95,9 +103,6 @@ namespace ArchiSteamFarm { [JsonProperty(Required = Required.DisallowNull)] internal readonly bool IsBotAccount = false; - [JsonProperty(Required = Required.DisallowNull)] - internal readonly bool SteamTradeMatcher = false; - [JsonProperty(Required = Required.DisallowNull)] internal readonly bool ForwardKeysToOtherBots = false; @@ -116,6 +121,9 @@ namespace ArchiSteamFarm { [JsonProperty(Required = Required.DisallowNull)] internal readonly byte SendTradePeriod = 0; + [JsonProperty(Required = Required.DisallowNull)] + internal readonly ETradingPreferences TradingPreferences = ETradingPreferences.AcceptDonations; + [JsonProperty(Required = Required.DisallowNull)] internal readonly byte AcceptConfirmationsPeriod = 0; diff --git a/ArchiSteamFarm/Trading.cs b/ArchiSteamFarm/Trading.cs index 05d680e2d..0887020a0 100644 --- a/ArchiSteamFarm/Trading.cs +++ b/ArchiSteamFarm/Trading.cs @@ -186,8 +186,8 @@ namespace ArchiSteamFarm { return null; } - // Always accept trades when we're not losing anything - if (tradeOffer.ItemsToGive.Count == 0) { + // Accept trades when we're not losing anything + if ((tradeOffer.ItemsToGive.Count == 0) && Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.AcceptDonations)) { // Unless it's steam fuckup and we're dealing with broken trade return tradeOffer.ItemsToReceive.Count > 0 ? new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.AcceptedWithoutItemLose) : new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.RejectedTemporarily); } @@ -198,7 +198,7 @@ namespace ArchiSteamFarm { } // If we don't have SteamTradeMatcher enabled, this is the end for us - if (!Bot.BotConfig.SteamTradeMatcher) { + if (!Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.SteamTradeMatcher)) { return new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.RejectedPermanently); } diff --git a/ArchiSteamFarm/config/example.json b/ArchiSteamFarm/config/example.json index c8e403413..40550c65a 100644 --- a/ArchiSteamFarm/config/example.json +++ b/ArchiSteamFarm/config/example.json @@ -16,13 +16,13 @@ "HandleOfflineMessages": false, "AcceptGifts": false, "IsBotAccount": false, - "SteamTradeMatcher": false, "ForwardKeysToOtherBots": false, "DistributeKeys": false, "ShutdownOnFarmingFinished": false, "SendOnFarmingFinished": false, "SteamTradeToken": null, "SendTradePeriod": 0, + "TradingPreferences": 1, "AcceptConfirmationsPeriod": 0, "CustomGamePlayedWhileFarming": null, "CustomGamePlayedWhileIdle": null, diff --git a/ConfigGenerator/BotConfig.cs b/ConfigGenerator/BotConfig.cs index 213470c56..0699fffbe 100644 --- a/ConfigGenerator/BotConfig.cs +++ b/ConfigGenerator/BotConfig.cs @@ -53,6 +53,13 @@ namespace ConfigGenerator { NamesDescending } + [Flags] + internal enum ETradingPreferences : byte { + None = 0, + AcceptDonations = 1, + SteamTradeMatcher = 2 + } + [Category("\t\tCore")] [JsonProperty(Required = Required.DisallowNull)] public bool Enabled { get; set; } = false; @@ -114,10 +121,6 @@ namespace ConfigGenerator { [JsonProperty(Required = Required.DisallowNull)] public bool IsBotAccount { get; set; } = false; - [Category("\tAdvanced")] - [JsonProperty(Required = Required.DisallowNull)] - public bool SteamTradeMatcher { get; set; } = false; - [JsonProperty(Required = Required.DisallowNull)] public bool ForwardKeysToOtherBots { get; set; } = false; @@ -137,6 +140,11 @@ namespace ConfigGenerator { [JsonProperty(Required = Required.DisallowNull)] public byte SendTradePeriod { get; set; } = 0; + [Category("\tAdvanced")] + [Editor(typeof(FlagEnumUIEditor), typeof(System.Drawing.Design.UITypeEditor))] + [JsonProperty(Required = Required.DisallowNull)] + public ETradingPreferences TradingPreferences { get; set; } = ETradingPreferences.AcceptDonations; + [Category("\tAdvanced")] [JsonProperty(Required = Required.DisallowNull)] public byte AcceptConfirmationsPeriod { get; set; } = 0; diff --git a/ConfigGenerator/ConfigGenerator.csproj b/ConfigGenerator/ConfigGenerator.csproj index ee0b6c15f..2e8f53209 100644 --- a/ConfigGenerator/ConfigGenerator.csproj +++ b/ConfigGenerator/ConfigGenerator.csproj @@ -66,6 +66,9 @@ Component + + Component + Component diff --git a/ConfigGenerator/FlagEnumEditor.cs b/ConfigGenerator/FlagEnumEditor.cs new file mode 100644 index 000000000..abada8a0d --- /dev/null +++ b/ConfigGenerator/FlagEnumEditor.cs @@ -0,0 +1,192 @@ +using System; +using System.ComponentModel; +using System.Drawing.Design; +using System.Linq; +using System.Windows.Forms; +using System.Windows.Forms.Design; + +namespace ConfigGenerator { + internal sealed class FlagCheckedListBox : CheckedListBox { + + internal FlagCheckedListBox() { + // This call is required by the Windows.Forms Form Designer. + InitializeComponent(); + } + + #region Component Designer generated code + private void InitializeComponent() { + // + // FlaggedCheckedListBox + // + CheckOnClick = true; + + } + #endregion + + // Adds an integer value and its associated description + private void Add(int v, string c) { + FlagCheckedListBoxItem item = new FlagCheckedListBoxItem(v, c); + Items.Add(item); + } + + protected override void OnItemCheck(ItemCheckEventArgs e) { + base.OnItemCheck(e); + + if (IsUpdatingCheckStates) { + return; + } + + // Get the checked/unchecked item + FlagCheckedListBoxItem item = Items[e.Index] as FlagCheckedListBoxItem; + // Update other items + UpdateCheckedItems(item, e.NewValue); + } + + // Checks/Unchecks items depending on the give bitvalue + private void UpdateCheckedItems(int value) { + + IsUpdatingCheckStates = true; + + // Iterate over all items + for (int i = 0; i < Items.Count; i++) { + FlagCheckedListBoxItem item = Items[i] as FlagCheckedListBoxItem; + if (item == null) { + continue; + } + + if (item.Value == 0) { + SetItemChecked(i, value == 0); + } else { + + // If the bit for the current item is on in the bitvalue, check it + if (((item.Value & value) == item.Value) && (item.Value != 0)) { + SetItemChecked(i, true); + } + // Otherwise uncheck it + else { + SetItemChecked(i, false); + } + } + } + + IsUpdatingCheckStates = false; + + } + + // Updates items in the checklistbox + // composite = The item that was checked/unchecked + // cs = The check state of that item + private void UpdateCheckedItems(FlagCheckedListBoxItem composite, CheckState cs) { + + // If the value of the item is 0, call directly. + if (composite.Value == 0) { + UpdateCheckedItems(0); + } + + + // Get the total value of all checked items + int sum = (from object t in Items select t as FlagCheckedListBoxItem).Where((item, i) => (item != null) && GetItemChecked(i)).Aggregate(0, (current, item) => current | item.Value); + + // If the item has been unchecked, remove its bits from the sum + if (cs == CheckState.Unchecked) { + sum = sum & ~composite.Value; + } + // If the item has been checked, combine its bits with the sum + else { + sum |= composite.Value; + } + + // Update all items in the checklistbox based on the final bit value + UpdateCheckedItems(sum); + + } + + private bool IsUpdatingCheckStates; + + // Gets the current bit value corresponding to all checked items + private int GetCurrentValue() => (from object t in Items select t as FlagCheckedListBoxItem).Where((item, i) => (item != null) && GetItemChecked(i)).Aggregate(0, (current, item) => current | item.Value); + + private Type EnumType; + private Enum _EnumValue; + + // Adds items to the checklistbox based on the members of the enum + private void FillEnumMembers() { + foreach (string name in Enum.GetNames(EnumType)) { + object val = Enum.Parse(EnumType, name); + int intVal = (int) Convert.ChangeType(val, typeof(int)); + + Add(intVal, name); + } + } + + // Checks/unchecks items based on the current value of the enum variable + private void ApplyEnumValue() { + int intVal = (int) Convert.ChangeType(_EnumValue, typeof(int)); + UpdateCheckedItems(intVal); + + } + + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public Enum EnumValue { + get { + object e = Enum.ToObject(EnumType, GetCurrentValue()); + return (Enum) e; + } + set { + + Items.Clear(); + _EnumValue = value; // Store the current enum value + EnumType = value.GetType(); // Store enum type + FillEnumMembers(); // Add items for enum members + ApplyEnumValue(); // Check/uncheck items depending on enum value + + } + } + + + } + + // Represents an item in the checklistbox + internal sealed class FlagCheckedListBoxItem { + public readonly int Value; + + private readonly string Caption; + + internal FlagCheckedListBoxItem(int v, string c) { + Value = v; + Caption = c; + } + + public override string ToString() => Caption; + } + + + // UITypeEditor for flag enums + internal sealed class FlagEnumUIEditor : UITypeEditor { + // The checklistbox + private readonly FlagCheckedListBox FlagEnumCb; + + public FlagEnumUIEditor() { + FlagEnumCb = new FlagCheckedListBox { BorderStyle = BorderStyle.None }; + } + + public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { + if ((context?.PropertyDescriptor == null) || (provider == null)) { + return null; + } + + IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService) provider.GetService(typeof(IWindowsFormsEditorService)); + + if (edSvc == null) { + return null; + } + + Enum e = (Enum) Convert.ChangeType(value, context.PropertyDescriptor.PropertyType); + FlagEnumCb.EnumValue = e; + edSvc.DropDownControl(FlagEnumCb); + return FlagEnumCb.EnumValue; + } + + public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) => UITypeEditorEditStyle.DropDown; + } +}