From 0fc5f540d8eda10d4318b094cd80226688c28368 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Tue, 6 Jul 2021 17:08:16 +0200 Subject: [PATCH] - Added Cloneable deep clone source generator nuget package - Configs are no cloned using generated clone, not by serializing/deserializing - Arrays/Lists (collections in geneeral) are still not cloned properly - Removed GetRawData from config as it is no longer needed, new clone is very fast - Added ICloneable which all configs implement - Cleaned up config classes/code --- src/NadekoBot/Bot.cs | 1 - src/NadekoBot/Common/Configs/BotConfig.cs | 12 +- src/NadekoBot/Common/ICloneable.cs | 7 + .../Administration/Services/SelfService.cs | 2 +- .../Modules/Gambling/Common/BetRoll.cs | 4 +- .../Modules/Gambling/Common/GamblingConfig.cs | 347 +++++++++--------- .../Modules/Gambling/Services/WaifuService.cs | 2 +- .../Modules/Games/Common/GamesConfig.cs | 29 +- .../Modules/Help/Services/HelpService.cs | 4 +- src/NadekoBot/Modules/Xp/Common/XpConfig.cs | 7 +- .../Modules/Xp/Services/XpService.cs | 5 +- src/NadekoBot/NadekoBot.csproj | 1 + src/NadekoBot/Services/CommandHandler.cs | 4 +- .../Services/Impl/CurrencyService.cs | 2 +- .../Services/Settings/ConfigServiceBase.cs | 46 +-- 15 files changed, 237 insertions(+), 236 deletions(-) create mode 100644 src/NadekoBot/Common/ICloneable.cs diff --git a/src/NadekoBot/Bot.cs b/src/NadekoBot/Bot.cs index 17b36ad8d..b5533265d 100644 --- a/src/NadekoBot/Bot.cs +++ b/src/NadekoBot/Bot.cs @@ -141,7 +141,6 @@ namespace NadekoBot .AddSingleton(x => (IReadyExecutor)x.GetRequiredService()); } - // todo no public bot attribute svcs.Scan(scan => scan .FromAssemblyOf() .AddClasses(classes => classes.AssignableToAny( diff --git a/src/NadekoBot/Common/Configs/BotConfig.cs b/src/NadekoBot/Common/Configs/BotConfig.cs index 28279b677..c62658cb9 100644 --- a/src/NadekoBot/Common/Configs/BotConfig.cs +++ b/src/NadekoBot/Common/Configs/BotConfig.cs @@ -1,5 +1,6 @@ ๏ปฟusing System.Collections.Generic; using System.Globalization; +using Cloneable; using NadekoBot.Common.Yml; using SixLabors.ImageSharp.PixelFormats; using YamlDotNet.Core; @@ -7,7 +8,8 @@ using YamlDotNet.Serialization; namespace NadekoBot.Common.Configs { - public sealed class BotConfig + [Cloneable] + public sealed partial class BotConfig : ICloneable { [Comment(@"DO NOT CHANGE")] public int Version { get; set; } @@ -66,6 +68,7 @@ note: This setting is primarily used if you're afraid of raids, or you're runnin servers might get hundreds of people join at once. This is used to prevent the bot from getting ratelimited, and (slightly) reduce the greet spam in those servers.")] public bool GroupGreets { get; set; } + [Comment(@"Whether the bot will rotate through all specified statuses. This setting can be changed via .rots command. See RotatingStatuses submodule in Administration.")] @@ -127,7 +130,8 @@ See RotatingStatuses submodule in Administration.")] } } - public class BlockedConfig + [Cloneable] + public sealed partial class BlockedConfig { public HashSet Commands { get; set; } public HashSet Modules { get; set; } @@ -139,7 +143,8 @@ See RotatingStatuses submodule in Administration.")] } } - public class ColorConfig + [Cloneable] + public partial class ColorConfig { [Comment(@"Color used for embed responses when command successfully executes")] public Rgba32 Ok { get; set; } @@ -157,6 +162,7 @@ See RotatingStatuses submodule in Administration.")] Pending = Rgba32.ParseHex("faa61a"); } } + public enum ConsoleOutputType { Normal = 0, diff --git a/src/NadekoBot/Common/ICloneable.cs b/src/NadekoBot/Common/ICloneable.cs new file mode 100644 index 000000000..d5062325b --- /dev/null +++ b/src/NadekoBot/Common/ICloneable.cs @@ -0,0 +1,7 @@ +๏ปฟnamespace NadekoBot.Common +{ + public interface ICloneable where T : new() + { + public T Clone(); + } +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Administration/Services/SelfService.cs b/src/NadekoBot/Modules/Administration/Services/SelfService.cs index d8f1273cb..b04222d95 100644 --- a/src/NadekoBot/Modules/Administration/Services/SelfService.cs +++ b/src/NadekoBot/Modules/Administration/Services/SelfService.cs @@ -233,7 +233,7 @@ namespace NadekoBot.Modules.Administration.Services public async Task LateExecute(IGuild guild, IUserMessage msg) { var bs = _bss.Data; - if (msg.Channel is IDMChannel && _bss.Data.ForwardMessages && ownerChannels.Any()) + if (msg.Channel is IDMChannel && bs.ForwardMessages && ownerChannels.Any()) { var title = _strings.GetText("dm_from") + $" [{msg.Author}]({msg.Author.Id})"; diff --git a/src/NadekoBot/Modules/Gambling/Common/BetRoll.cs b/src/NadekoBot/Modules/Gambling/Common/BetRoll.cs index 5caa8f1ce..60f38d80b 100644 --- a/src/NadekoBot/Modules/Gambling/Common/BetRoll.cs +++ b/src/NadekoBot/Modules/Gambling/Common/BetRoll.cs @@ -13,10 +13,10 @@ namespace NadekoBot.Modules.Gambling.Common } - private readonly IOrderedEnumerable _thresholdPairs; + private readonly IOrderedEnumerable _thresholdPairs; private readonly Random _rng; - public Betroll(GamblingConfig.BetRollConfig settings) + public Betroll(BetRollConfig settings) { _thresholdPairs = settings.Pairs.OrderByDescending(x => x.WhenAbove); _rng = new Random(); diff --git a/src/NadekoBot/Modules/Gambling/Common/GamblingConfig.cs b/src/NadekoBot/Modules/Gambling/Common/GamblingConfig.cs index 4e5d23333..00f380012 100644 --- a/src/NadekoBot/Modules/Gambling/Common/GamblingConfig.cs +++ b/src/NadekoBot/Modules/Gambling/Common/GamblingConfig.cs @@ -1,10 +1,13 @@ ๏ปฟusing System; using System.Collections.Generic; +using Cloneable; +using NadekoBot.Common; using NadekoBot.Common.Yml; namespace NadekoBot.Modules.Gambling.Common { - public sealed class GamblingConfig + [Cloneable] + public sealed partial class GamblingConfig : ICloneable { public GamblingConfig() { @@ -17,10 +20,10 @@ namespace NadekoBot.Modules.Gambling.Common Timely = new TimelyConfig(); Decay = new DecayConfig(); } - + [Comment(@"DO NOT CHANGE")] public int Version { get; set; } = 1; - + [Comment(@"Currency settings")] public CurrencyConfig Currency { get; set; } @@ -30,257 +33,247 @@ namespace NadekoBot.Modules.Gambling.Common [Comment(@"Maximum amount users can bet Set 0 for unlimited")] public int MaxBet { get; set; } = 0; - + [Comment(@"Settings for betflip command")] public BetFlipConfig BetFlip { get; set; } [Comment(@"Settings for betroll command")] public BetRollConfig BetRoll { get; set; } - + [Comment(@"Automatic currency generation settings.")] public GenerationConfig Generation { get; set; } - + [Comment(@"Settings for timely command (letting people claim X amount of currency every Y hours)")] public TimelyConfig Timely { get; set; } [Comment(@"How much will each user's owned currency decay over time.")] public DecayConfig Decay { get; set; } + [Comment(@"Settings for Wheel Of Fortune command.")] public WheelOfFortuneSettings WheelOfFortune { get; set; } + [Comment(@"Settings related to waifus")] public WaifuConfig Waifu { get; set; } - + [Comment(@"Amount of currency selfhosters will get PER pledged dollar CENT. 1 = 100 currency per $. Used almost exclusively on public nadeko.")] public decimal PatreonCurrencyPerCent { get; set; } = 1; + } - public class CurrencyConfig - { - [Comment(@"What is the emoji/character which represents the currency")] - public string Sign { get; set; } = "๐ŸŒธ"; - - [Comment(@"What is the name of the currency")] - public string Name { get; set; } = "Nadeko Flower"; - } + public class CurrencyConfig + { + [Comment(@"What is the emoji/character which represents the currency")] + public string Sign { get; set; } = "๐ŸŒธ"; - public class TimelyConfig - { - [Comment(@"How much currency will the users get every time they run .timely command + [Comment(@"What is the name of the currency")] + public string Name { get; set; } = "Nadeko Flower"; + } + + [Cloneable] + public partial class TimelyConfig + { + [Comment(@"How much currency will the users get every time they run .timely command setting to 0 or less will disable this feature")] - public int Amount { get; set; } = 0; + public int Amount { get; set; } = 0; - [Comment(@"How often (in hours) can users claim currency with .timely command + [Comment(@"How often (in hours) can users claim currency with .timely command setting to 0 or less will disable this feature")] - public int Cooldown { get; set; } = 24; - } + public int Cooldown { get; set; } = 24; + } - public class BetFlipConfig - { - [Comment(@"Bet multiplier if user guesses correctly")] - public decimal Multiplier { get; set; } = 1.95M; - } + [Cloneable] + public partial class BetFlipConfig + { + [Comment(@"Bet multiplier if user guesses correctly")] + public decimal Multiplier { get; set; } = 1.95M; + } - public class BetRollConfig - { - [Comment(@"When betroll is played, user will roll a number 0-100. + [Cloneable] + public partial class BetRollConfig + { + [Comment(@"When betroll is played, user will roll a number 0-100. This setting will describe which multiplier is used for when the roll is higher than the given number. Doesn't have to be ordered.")] - public Pair[] Pairs { get; set; } = Array.Empty(); + public BetRollPair[] Pairs { get; set; } = Array.Empty(); - public BetRollConfig() - { - Pairs = new BetRollConfig.Pair[] - { - new BetRollConfig.Pair(99, 10), - new BetRollConfig.Pair(90, 4), - new BetRollConfig.Pair(66, 2) - }; - } - - public class Pair - { - - public int WhenAbove { get; set; } - - public float MultiplyBy { get; set; } - - public Pair() - { - - } - - public Pair(int threshold, int multiplier) - { - WhenAbove = threshold; - MultiplyBy = multiplier; - } - } - } - - public class GenerationConfig + public BetRollConfig() { - [Comment(@"when currency is generated, should it also have a random password + Pairs = new BetRollPair[] + { + new BetRollPair { WhenAbove = 99, MultiplyBy = 10 }, + new BetRollPair { WhenAbove = 90, MultiplyBy = 4 }, + new BetRollPair { WhenAbove = 66, MultiplyBy = 2 } + }; + } + } + + [Cloneable] + public partial class GenerationConfig + { + [Comment(@"when currency is generated, should it also have a random password associated with it which users have to type after the .pick command in order to get it")] - public bool HasPassword { get; set; } = true; + public bool HasPassword { get; set; } = true; - [Comment(@"Every message sent has a certain % chance to generate the currency + [Comment(@"Every message sent has a certain % chance to generate the currency specify the percentage here (1 being 100%, 0 being 0% - for example default is 0.02, which is 2%")] - public decimal Chance { get; set; } = 0.02M; + public decimal Chance { get; set; } = 0.02M; - [Comment(@"How many seconds have to pass for the next message to have a chance to spawn currency")] - public int GenCooldown { get; set; } = 10; + [Comment(@"How many seconds have to pass for the next message to have a chance to spawn currency")] + public int GenCooldown { get; set; } = 10; - [Comment(@"Minimum amount of currency that can spawn")] - public int MinAmount { get; set; } = 1; + [Comment(@"Minimum amount of currency that can spawn")] + public int MinAmount { get; set; } = 1; - [Comment(@"Maximum amount of currency that can spawn. + [Comment(@"Maximum amount of currency that can spawn. Set to the same value as MinAmount to always spawn the same amount")] - public int MaxAmount { get; set; } = 1; - } + public int MaxAmount { get; set; } = 1; + } - public class DecayConfig - { - [Comment(@"Percentage of user's current currency which will be deducted every 24h. + [Cloneable] + public partial class DecayConfig + { + [Comment(@"Percentage of user's current currency which will be deducted every 24h. 0 - 1 (1 is 100%, 0.5 50%, 0 disabled)")] - public decimal Percent { get; set; } = 0; + public decimal Percent { get; set; } = 0; - [Comment(@"Maximum amount of user's currency that can decay at each interval. 0 for unlimited.")] - public int MaxDecay { get; set; } = 0; + [Comment(@"Maximum amount of user's currency that can decay at each interval. 0 for unlimited.")] + public int MaxDecay { get; set; } = 0; - [Comment(@"Only users who have more than this amount will have their currency decay.")] - public int MinThreshold { get; set; } = 99; + [Comment(@"Only users who have more than this amount will have their currency decay.")] + public int MinThreshold { get; set; } = 99; - [Comment(@"How often, in hours, does the decay run. Default is 24 hours")] - public int HourInterval { get; set; } = 24; - } + [Comment(@"How often, in hours, does the decay run. Default is 24 hours")] + public int HourInterval { get; set; } = 24; + } - public class WheelOfFortuneSettings + [Cloneable] + public partial class WheelOfFortuneSettings + { + [Comment(@"Self-Explanatory. Has to have 8 values, otherwise the command won't work.")] + public decimal[] Multipliers { get; set; } + + public WheelOfFortuneSettings() { - [Comment(@"Self-Explanatory. Has to have 8 values, otherwise the command won't work.")] - public decimal[] Multipliers { get; set; } - - public WheelOfFortuneSettings() + Multipliers = new decimal[] { - Multipliers = new decimal[] - { - 1.7M, - 1.5M, - 0.2M, - 0.1M, - 0.3M, - 0.5M, - 1.2M, - 2.4M, - }; - } + 1.7M, + 1.5M, + 0.2M, + 0.1M, + 0.3M, + 0.5M, + 1.2M, + 2.4M, + }; } + } - public class WaifuConfig + [Cloneable] + public sealed partial class WaifuConfig + { + [Comment(@"Minimum price a waifu can have")] + public int MinPrice { get; set; } = 50; + + public MultipliersData Multipliers { get; set; } = new MultipliersData(); + + [Comment(@"List of items available for gifting.")] + public List Items { get; set; } = new List(); + + public WaifuConfig() { - [Comment(@"Minimum price a waifu can have")] - public int MinPrice { get; set; } = 50; - public MultipliersData Multipliers { get; set; } = new MultipliersData(); - - [Comment(@"List of items available for gifting.")] - public List Items { get; set; } = new List(); - - public WaifuConfig() + Items = new() { - Items = new List() - { - new WaifuItemModel("๐Ÿฅ”", 5, "Potato"), - new WaifuItemModel("๐Ÿช", 10, "Cookie"), - new WaifuItemModel("๐Ÿฅ–", 20, "Bread"), - new WaifuItemModel("๐Ÿญ", 30, "Lollipop"), - new WaifuItemModel("๐ŸŒน", 50, "Rose"), - new WaifuItemModel("๐Ÿบ", 70, "Beer"), - new WaifuItemModel("๐ŸŒฎ", 85, "Taco"), - new WaifuItemModel("๐Ÿ’Œ", 100, "LoveLetter"), - new WaifuItemModel("๐Ÿฅ›", 125, "Milk"), - new WaifuItemModel("๐Ÿ•", 150, "Pizza"), - new WaifuItemModel("๐Ÿซ", 200, "Chocolate"), - new WaifuItemModel("๐Ÿฆ", 250, "Icecream"), - new WaifuItemModel("๐Ÿฃ", 300, "Sushi"), - new WaifuItemModel("๐Ÿš", 400, "Rice"), - new WaifuItemModel("๐Ÿ‰", 500, "Watermelon"), - new WaifuItemModel("๐Ÿฑ", 600, "Bento"), - new WaifuItemModel("๐ŸŽŸ", 800, "MovieTicket"), - new WaifuItemModel("๐Ÿฐ", 1000, "Cake"), - new WaifuItemModel("๐Ÿ“”", 1500, "Book"), - new WaifuItemModel("๐Ÿฑ", 2000, "Cat"), - new WaifuItemModel("๐Ÿถ", 2001, "Dog"), - new WaifuItemModel("๐Ÿผ", 2500, "Panda"), - new WaifuItemModel("๐Ÿ’„", 3000, "Lipstick"), - new WaifuItemModel("๐Ÿ‘›", 3500, "Purse"), - new WaifuItemModel("๐Ÿ“ฑ", 4000, "iPhone"), - new WaifuItemModel("๐Ÿ‘—", 4500, "Dress"), - new WaifuItemModel("๐Ÿ’ป", 5000, "Laptop"), - new WaifuItemModel("๐ŸŽป", 7500, "Violin"), - new WaifuItemModel("๐ŸŽน", 8000, "Piano"), - new WaifuItemModel("๐Ÿš—", 9000, "Car"), - new WaifuItemModel("๐Ÿ’", 10000, "Ring"), - new WaifuItemModel("๐Ÿ›ณ", 12000, "Ship"), - new WaifuItemModel("๐Ÿ ", 15000, "House"), - new WaifuItemModel("๐Ÿš", 20000, "Helicopter"), - new WaifuItemModel("๐Ÿš€", 30000, "Spaceship"), - new WaifuItemModel("๐ŸŒ•", 50000, "Moon") - }; - } + new("๐Ÿฅ”", 5, "Potato"), + new("๐Ÿช", 10, "Cookie"), + new("๐Ÿฅ–", 20, "Bread"), + new("๐Ÿญ", 30, "Lollipop"), + new("๐ŸŒน", 50, "Rose"), + new("๐Ÿบ", 70, "Beer"), + new("๐ŸŒฎ", 85, "Taco"), + new("๐Ÿ’Œ", 100, "LoveLetter"), + new("๐Ÿฅ›", 125, "Milk"), + new("๐Ÿ•", 150, "Pizza"), + new("๐Ÿซ", 200, "Chocolate"), + new("๐Ÿฆ", 250, "Icecream"), + new("๐Ÿฃ", 300, "Sushi"), + new("๐Ÿš", 400, "Rice"), + new("๐Ÿ‰", 500, "Watermelon"), + new("๐Ÿฑ", 600, "Bento"), + new("๐ŸŽŸ", 800, "MovieTicket"), + new("๐Ÿฐ", 1000, "Cake"), + new("๐Ÿ“”", 1500, "Book"), + new("๐Ÿฑ", 2000, "Cat"), + new("๐Ÿถ", 2001, "Dog"), + new("๐Ÿผ", 2500, "Panda"), + new("๐Ÿ’„", 3000, "Lipstick"), + new("๐Ÿ‘›", 3500, "Purse"), + new("๐Ÿ“ฑ", 4000, "iPhone"), + new("๐Ÿ‘—", 4500, "Dress"), + new("๐Ÿ’ป", 5000, "Laptop"), + new("๐ŸŽป", 7500, "Violin"), + new("๐ŸŽน", 8000, "Piano"), + new("๐Ÿš—", 9000, "Car"), + new("๐Ÿ’", 10000, "Ring"), + new("๐Ÿ›ณ", 12000, "Ship"), + new("๐Ÿ ", 15000, "House"), + new("๐Ÿš", 20000, "Helicopter"), + new("๐Ÿš€", 30000, "Spaceship"), + new("๐ŸŒ•", 50000, "Moon") + }; + } + } - - public class MultipliersData - { - [Comment(@"Multiplier for waifureset. Default 150. + [Cloneable] + public sealed partial class MultipliersData + { + [Comment(@"Multiplier for waifureset. Default 150. Formula (at the time of writing this): price = (waifu_price * 1.25f) + ((number_of_divorces + changes_of_heart + 2) * WaifuReset) rounded up")] - public int WaifuReset { get; set; } = 150; + public int WaifuReset { get; set; } = 150; - [Comment(@"The minimum amount of currency that you have to pay + [Comment(@"The minimum amount of currency that you have to pay in order to buy a waifu who doesn't have a crush on you. Default is 1.1 Example: If a waifu is worth 100, you will have to pay at least 100 * NormalClaim currency to claim her. (100 * 1.1 = 110)")] - public decimal NormalClaim { get; set; } = 1.1m; + public decimal NormalClaim { get; set; } = 1.1m; - [Comment(@"The minimum amount of currency that you have to pay + [Comment(@"The minimum amount of currency that you have to pay in order to buy a waifu that has a crush on you. Default is 0.88 Example: If a waifu is worth 100, you will have to pay at least 100 * CrushClaim currency to claim her. (100 * 0.88 = 88)")] - public decimal CrushClaim { get; set; } = 0.88M; + public decimal CrushClaim { get; set; } = 0.88M; - [Comment(@"When divorcing a waifu, her new value will be her current value multiplied by this number. + [Comment(@"When divorcing a waifu, her new value will be her current value multiplied by this number. Default 0.75 (meaning will lose 25% of her value)")] - public decimal DivorceNewValue { get; set; } = 0.75M; + public decimal DivorceNewValue { get; set; } = 0.75M; - [Comment(@"All gift prices will be multiplied by this number. + [Comment(@"All gift prices will be multiplied by this number. Default 1 (meaning no effect)")] - public decimal AllGiftPrices { get; set; } = 1.0M; + public decimal AllGiftPrices { get; set; } = 1.0M; - [Comment(@"What percentage of the value of the gift will a waifu gain when she's gifted. + [Comment(@"What percentage of the value of the gift will a waifu gain when she's gifted. Default 0.95 (meaning 95%) Example: If a waifu is worth 1000, and she receives a gift worth 100, her new value will be 1095)")] - public decimal GiftEffect { get; set; } = 0.95M; - } - } + public decimal GiftEffect { get; set; } = 0.95M; } - - public class WaifuItemModel + + [Cloneable] + public sealed partial class WaifuItemModel { public string ItemEmoji { get; set; } - public int Price { get; set; } - public string Name { get; set; } public WaifuItemModel() { - + } - + public WaifuItemModel(string itemEmoji, int price, string name) { ItemEmoji = itemEmoji; @@ -290,4 +283,12 @@ Example: If a waifu is worth 1000, and she receives a gift worth 100, her new va public override string ToString() => Name; } + + + [Cloneable] + public sealed partial class BetRollPair + { + public int WhenAbove { get; set; } + public float MultiplyBy { get; set; } + } } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/Services/WaifuService.cs b/src/NadekoBot/Modules/Gambling/Services/WaifuService.cs index 8d8ec03f8..acab14878 100644 --- a/src/NadekoBot/Modules/Gambling/Services/WaifuService.cs +++ b/src/NadekoBot/Modules/Gambling/Services/WaifuService.cs @@ -511,7 +511,7 @@ namespace NadekoBot.Modules.Gambling.Services public IReadOnlyList GetWaifuItems() { var conf = _gss.Data; - return _gss.Data.Waifu.Items + return conf.Waifu.Items .Select(x => new WaifuItemModel(x.ItemEmoji, (int)(x.Price * conf.Waifu.Multipliers.AllGiftPrices), x.Name)) .ToList(); } diff --git a/src/NadekoBot/Modules/Games/Common/GamesConfig.cs b/src/NadekoBot/Modules/Games/Common/GamesConfig.cs index b342f550d..9e88c7969 100644 --- a/src/NadekoBot/Modules/Games/Common/GamesConfig.cs +++ b/src/NadekoBot/Modules/Games/Common/GamesConfig.cs @@ -1,9 +1,12 @@ ๏ปฟusing System.Collections.Generic; +using Cloneable; +using NadekoBot.Common; using NadekoBot.Common.Yml; namespace NadekoBot.Modules.Games.Common { - public sealed class GamesConfig + [Cloneable] + public sealed partial class GamesConfig : ICloneable { [Comment("Trivia related settings (.t command)")] public TriviaConfig Trivia { get; set; } = new TriviaConfig() @@ -11,7 +14,7 @@ namespace NadekoBot.Modules.Games.Common CurrencyReward = 0, MinimumWinReq = 1, }; - + [Comment("List of responses for the .8ball command. A random one will be selected every time")] public List EightBallResponses { get; set; } = new List() { @@ -43,18 +46,19 @@ namespace NadekoBot.Modules.Games.Common [Comment("List of animals which will be used for the animal race game (.race)")] public List RaceAnimals { get; set; } = new List() { - new RaceAnimal {Icon = "๐Ÿผ", Name = "Panda"}, - new RaceAnimal {Icon = "๐Ÿป", Name = "Bear"}, - new RaceAnimal {Icon = "๐Ÿง", Name = "Pengu"}, - new RaceAnimal {Icon = "๐Ÿจ", Name = "Koala"}, - new RaceAnimal {Icon = "๐Ÿฌ", Name = "Dolphin"}, - new RaceAnimal {Icon = "๐Ÿž", Name = "Ladybird"}, - new RaceAnimal {Icon = "๐Ÿฆ€", Name = "Crab"}, - new RaceAnimal {Icon = "๐Ÿฆ„", Name = "Unicorn"} + new RaceAnimal { Icon = "๐Ÿผ", Name = "Panda" }, + new RaceAnimal { Icon = "๐Ÿป", Name = "Bear" }, + new RaceAnimal { Icon = "๐Ÿง", Name = "Pengu" }, + new RaceAnimal { Icon = "๐Ÿจ", Name = "Koala" }, + new RaceAnimal { Icon = "๐Ÿฌ", Name = "Dolphin" }, + new RaceAnimal { Icon = "๐Ÿž", Name = "Ladybird" }, + new RaceAnimal { Icon = "๐Ÿฆ€", Name = "Crab" }, + new RaceAnimal { Icon = "๐Ÿฆ„", Name = "Unicorn" } }; } - public sealed class TriviaConfig + [Cloneable] + public sealed partial class TriviaConfig { [Comment("The amount of currency awarded to the winner of the trivia game.")] public long CurrencyReward { get; set; } = 0; @@ -64,7 +68,8 @@ a smaller win requirement than the one specified by this setting.")] public int MinimumWinReq { get; set; } = 1; } - public sealed class RaceAnimal + [Cloneable] + public sealed partial class RaceAnimal { public string Icon { get; set; } public string Name { get; set; } diff --git a/src/NadekoBot/Modules/Help/Services/HelpService.cs b/src/NadekoBot/Modules/Help/Services/HelpService.cs index 530dcc11a..97fc6cc74 100644 --- a/src/NadekoBot/Modules/Help/Services/HelpService.cs +++ b/src/NadekoBot/Modules/Help/Services/HelpService.cs @@ -34,8 +34,8 @@ namespace NadekoBot.Modules.Help.Services _rep = new ReplacementBuilder() - .WithOverride("%prefix%", () => _bss.GetRawData().Prefix) - .WithOverride("%bot.prefix%", () => _bss.GetRawData().Prefix) + .WithOverride("%prefix%", () => _bss.Data.Prefix) + .WithOverride("%bot.prefix%", () => _bss.Data.Prefix) .Build(); } diff --git a/src/NadekoBot/Modules/Xp/Common/XpConfig.cs b/src/NadekoBot/Modules/Xp/Common/XpConfig.cs index 754d4f294..ad0042e28 100644 --- a/src/NadekoBot/Modules/Xp/Common/XpConfig.cs +++ b/src/NadekoBot/Modules/Xp/Common/XpConfig.cs @@ -1,8 +1,11 @@ -๏ปฟusing NadekoBot.Common.Yml; +๏ปฟusing Cloneable; +using NadekoBot.Common; +using NadekoBot.Common.Yml; namespace NadekoBot.Modules.Xp { - public sealed class XpConfig + [Cloneable] + public sealed partial class XpConfig : ICloneable { [Comment(@"DO NOT CHANGE")] public int Version { get; set; } = 2; diff --git a/src/NadekoBot/Modules/Xp/Services/XpService.cs b/src/NadekoBot/Modules/Xp/Services/XpService.cs index 4067644ed..07973d22a 100644 --- a/src/NadekoBot/Modules/Xp/Services/XpService.cs +++ b/src/NadekoBot/Modules/Xp/Services/XpService.cs @@ -623,15 +623,16 @@ namespace NadekoBot.Modules.Xp.Services if (!ShouldTrackXp(user, arg.Channel.Id)) return; + var xpConf = _xpConfig.Data; var xp = 0; if (arg.Attachments.Any(a => a.Height >= 128 && a.Width >= 128)) { - xp = _xpConfig.GetRawData().XpFromImage; + xp = xpConf.XpFromImage; } if (arg.Content.Contains(' ') || arg.Content.Length >= 5) { - xp = Math.Max(xp, _xpConfig.GetRawData().XpPerMessage); + xp = Math.Max(xp, xpConf.XpPerMessage); } if (xp <= 0) diff --git a/src/NadekoBot/NadekoBot.csproj b/src/NadekoBot/NadekoBot.csproj index 3521c4f11..2b67004a1 100644 --- a/src/NadekoBot/NadekoBot.csproj +++ b/src/NadekoBot/NadekoBot.csproj @@ -11,6 +11,7 @@ + diff --git a/src/NadekoBot/Services/CommandHandler.cs b/src/NadekoBot/Services/CommandHandler.cs index 3b001a9bc..d994ad252 100644 --- a/src/NadekoBot/Services/CommandHandler.cs +++ b/src/NadekoBot/Services/CommandHandler.cs @@ -142,7 +142,7 @@ namespace NadekoBot.Services private Task LogSuccessfulExecution(IUserMessage usrMsg, ITextChannel channel, params int[] execPoints) { - if (_bss.GetRawData().ConsoleOutputType == ConsoleOutputType.Normal) + if (_bss.Data.ConsoleOutputType == ConsoleOutputType.Normal) { Log.Information($"Command Executed after " + string.Join("/", execPoints.Select(x => (x * _oneThousandth).ToString("F3"))) + "s\n\t" + "User: {0}\n\t" + @@ -168,7 +168,7 @@ namespace NadekoBot.Services private void LogErroredExecution(string errorMessage, IUserMessage usrMsg, ITextChannel channel, params int[] execPoints) { - if (_bss.GetRawData().ConsoleOutputType == ConsoleOutputType.Normal) + if (_bss.Data.ConsoleOutputType == ConsoleOutputType.Normal) { Log.Warning($"Command Errored after " + string.Join("/", execPoints.Select(x => (x * _oneThousandth).ToString("F3"))) + "s\n\t" + "User: {0}\n\t" + diff --git a/src/NadekoBot/Services/Impl/CurrencyService.cs b/src/NadekoBot/Services/Impl/CurrencyService.cs index 35a95bf81..9471f2fe6 100644 --- a/src/NadekoBot/Services/Impl/CurrencyService.cs +++ b/src/NadekoBot/Services/Impl/CurrencyService.cs @@ -83,7 +83,7 @@ namespace NadekoBot.Services .EmbedAsync(new EmbedBuilder() .WithOkColor() .WithTitle($"Received Currency") - .AddField("Amount", amount + _gss.Data.Currency.Sign) + .AddField("Amount", amount + sign) .AddField("Reason", reason)); } catch diff --git a/src/NadekoBot/Services/Settings/ConfigServiceBase.cs b/src/NadekoBot/Services/Settings/ConfigServiceBase.cs index aed66a719..bbf2d84bd 100644 --- a/src/NadekoBot/Services/Settings/ConfigServiceBase.cs +++ b/src/NadekoBot/Services/Settings/ConfigServiceBase.cs @@ -4,14 +4,10 @@ using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; -using System.Text.Json; using System.Threading.Tasks; using NadekoBot.Common.Yml; using NadekoBot.Common; using NadekoBot.Common.Configs; -using NadekoBot.Common.JsonConverters; -using Rgba32Converter = NadekoBot.Common.JsonConverters.Rgba32Converter; -using CultureInfoConverter = NadekoBot.Common.JsonConverters.CultureInfoConverter; namespace NadekoBot.Services { @@ -20,7 +16,7 @@ namespace NadekoBot.Services /// /// Type of the settings public abstract class ConfigServiceBase : IConfigService - where TSettings : new() + where TSettings : ICloneable, new() { protected readonly string _filePath; protected readonly IConfigSeria _serializer; @@ -29,8 +25,8 @@ namespace NadekoBot.Services protected TSettings _data; - // todo this has to be protected from mutation - public TSettings Data => _data; + // todo future config arrays are not copied - they're not protected from mutations + public TSettings Data => _data.Clone(); public abstract string Name { get; } @@ -65,21 +61,6 @@ namespace NadekoBot.Services return default; } - private static readonly JsonSerializerOptions serializerOptions = new JsonSerializerOptions() - { - MaxDepth = 0, - Converters = { new Rgba32Converter(), new CultureInfoConverter() } - }; - private TSettings CreateCopy() - { - var serializedData = JsonSerializer.Serialize(_data, serializerOptions); - return JsonSerializer.Deserialize(serializedData, serializerOptions); - - // var serializedData = _serializer.Serialize(_data); - // - // return _serializer.Deserialize(serializedData); - } - /// /// Loads data from disk. If file doesn't exist, it will be created with default values /// @@ -114,14 +95,6 @@ namespace NadekoBot.Services } - public void ModifyConfig(Action action) - { - var copy = CreateCopy(); - action(copy); - _data = copy; - Save(); - PublishChange(); - } private void Save() { var strData = _serializer.Serialize(_data); @@ -162,9 +135,7 @@ namespace NadekoBot.Services var expr = (MemberExpression)selector.Body; var prop = (PropertyInfo)expr.Member; - var expressions = new List() - { - }; + var expressions = new List(); while (true) { @@ -224,6 +195,13 @@ namespace NadekoBot.Services return success; } - public TSettings GetRawData() => _data; + public void ModifyConfig(Action action) + { + var copy = Data; + action(copy); + _data = copy; + Save(); + PublishChange(); + } } } \ No newline at end of file