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;
+ }
+}