using System; using System.Reflection; using Vintagestory.API.Common; using Vintagestory.API.Config; using Vintagestory.API.Server; namespace OrekiWoofsBees.Common.Configs; public static class ConfigCommands { public static void Register( IChatCommandApi chatApi, string commandName, string langDomain, bool serverSide, Func getInstance, Action saveConfig) { Register(chatApi.Create(commandName), chatApi, langDomain, serverSide, getInstance, saveConfig); } public static void Register( IChatCommand builder, IChatCommandApi chatApi, string langDomain, bool serverSide, Func getInstance, Action saveConfig) { if (serverSide) builder = builder.RequiresPrivilege(Privilege.controlserver); var p = chatApi.Parsers; foreach (var prop in typeof(T).GetProperties()) { var attr = prop.GetCustomAttribute(); if (attr == null || attr.ServerSide != serverSide) continue; var name = prop.Name; var descKey = $"{langDomain}:config-desc-{name}"; OnCommandDelegate handler; ICommandArgumentParser parser; if (prop.PropertyType == typeof(int)) { parser = p.OptionalIntRange("value", (int)attr.Min, (int)attr.Max); handler = args => HandleOptional(args, name, descKey, () => $"{prop.GetValue(getInstance())}", () => { prop.SetValue(getInstance(), (int)args.Parsers[0].GetValue()!); saveConfig(serverSide); }, () => args.Parsers[0].GetValue() is int); } else if (prop.PropertyType == typeof(float)) { parser = ParserExtensions.OptionalFloatRange("value", (float)attr.Min, (float)attr.Max); handler = args => HandleOptional(args, name, descKey, () => $"{(float)prop.GetValue(getInstance())!:G}", () => { prop.SetValue(getInstance(), (float)args.Parsers[0].GetValue()!); saveConfig(serverSide); }, () => args.Parsers[0].GetValue() is float); } else if (prop.PropertyType == typeof(bool)) { parser = p.OptionalBool("value"); handler = args => HandleOptional(args, name, descKey, () => $"{prop.GetValue(getInstance())}", () => { prop.SetValue(getInstance(), (bool)args.Parsers[0].GetValue()!); saveConfig(serverSide); }, () => args.Parsers[0].GetValue() is bool); } else if (prop.PropertyType == typeof(string)) { parser = p.OptionalWordRange("value", attr.AllowedValues); handler = args => HandleOptional(args, name, descKey, () => $"{prop.GetValue(getInstance())}", () => { prop.SetValue(getInstance(), (string)args.Parsers[0].GetValue()!); saveConfig(serverSide); }, () => args.Parsers[0].GetValue() is string); } else continue; builder .BeginSubCommand(name) .WithDescription(Lang.Get(descKey)) .WithArgs(parser) .HandleWith(handler) .EndSubCommand(); } } private static TextCommandResult HandleOptional( TextCommandCallingArgs args, string name, string descKey, Func formatValue, Action applyAndSave, Func canParse) { if (args.Parsers[0].IsMissing) return TextCommandResult.Success($"{Lang.Get(descKey)}\n{name}={formatValue()}"); if (!canParse()) return TextCommandResult.Error("Couldn't parse."); applyAndSave(); return TextCommandResult.Success($"{name}={formatValue()}"); } }