using System; using System.Xml.Linq; using Barotrauma.LuaCs.Data; using Barotrauma.LuaCs; using OneOf; namespace Barotrauma.LuaCs.Data; public interface ISettingsRegistrationProvider : IService { void RegisterTypeProviders(IConfigService configService, Func, bool> valueChangePredicate); } public class SettingsEntryRegistrar : ISettingsRegistrationProvider { private ILuaCsInfoProvider _infoProvider; public SettingsEntryRegistrar(ILuaCsInfoProvider infoProvider) { _infoProvider = infoProvider; } public void RegisterTypeProviders(IConfigService configService, Func, bool> valueChangePredicate) { RegisterSettingEntry(configService, "bool", valueChangePredicate); RegisterSettingEntry(configService, "byte", valueChangePredicate); RegisterSettingEntry(configService, "sbyte", valueChangePredicate); RegisterSettingEntry(configService, "short", valueChangePredicate); RegisterSettingEntry(configService, "ushort", valueChangePredicate); RegisterSettingEntry(configService, "int", valueChangePredicate); RegisterSettingEntry(configService, "uint", valueChangePredicate); RegisterSettingEntry(configService, "long", valueChangePredicate); RegisterSettingEntry(configService, "ulong", valueChangePredicate); RegisterSettingEntry(configService, "string", valueChangePredicate); RegisterSettingEntry(configService, "float", valueChangePredicate); RegisterSettingEntry(configService, "single", valueChangePredicate); RegisterSettingEntry(configService, "double", valueChangePredicate); // ISettingRangeBase configService.RegisterSettingTypeInitializer("rangeInt", cfgInfo => { return new SettingRangeInt.RangeFactory().CreateInstance(cfgInfo.Info, (val) => IsValueChangeAllowed(cfgInfo.Info, val, valueChangePredicate)); }); configService.RegisterSettingTypeInitializer("rangeFloat", cfgInfo => { return new SettingRangeFloat.RangeFactory().CreateInstance(cfgInfo.Info, (val) => IsValueChangeAllowed(cfgInfo.Info, val, valueChangePredicate)); }); #if CLIENT configService.RegisterSettingTypeInitializer("control" , cfgInfo => { return new SettingControl.Factory().CreateInstance(cfgInfo.Info, val => IsValueChangeAllowed(cfgInfo.Info, val, valueChangePredicate)); }); #endif RegisterSettingList(configService, "listBool", valueChangePredicate); RegisterSettingList(configService, "listByte", valueChangePredicate); RegisterSettingList(configService, "listSbyte", valueChangePredicate); RegisterSettingList(configService, "listShort", valueChangePredicate); RegisterSettingList(configService, "listUshort", valueChangePredicate); RegisterSettingList(configService, "listInt", valueChangePredicate); RegisterSettingList(configService, "listUint", valueChangePredicate); RegisterSettingList(configService, "listLong", valueChangePredicate); RegisterSettingList(configService, "listUlong", valueChangePredicate); RegisterSettingList(configService, "listString", valueChangePredicate); RegisterSettingList(configService, "listFloat", valueChangePredicate); RegisterSettingList(configService, "listSingle", valueChangePredicate); RegisterSettingList(configService, "listDouble", valueChangePredicate); } private void RegisterSettingList(IConfigService configService, string typeName, Func, bool> valueChangePredicate) where T : IEquatable, IConvertible { configService.RegisterSettingTypeInitializer(typeName, cfgInfo => { return new SettingList.LFactory().CreateInstance(cfgInfo.Info, (val) => IsValueChangeAllowed(cfgInfo.Info, val, valueChangePredicate)); }); } private void RegisterSettingEntry(IConfigService configService, string typeName, Func, bool> valueChangePredicate) where T : IEquatable, IConvertible { configService.RegisterSettingTypeInitializer(typeName, cfgInfo => { return new SettingEntry.Factory().CreateInstance(cfgInfo.Info, (val) => IsValueChangeAllowed(cfgInfo.Info, val, valueChangePredicate)); }); } private bool IsValueChangeAllowed(IConfigInfo info, OneOf newValue, Func, bool> valueChangePredicate) { #if CLIENT return !info.Element.GetAttributeBool("ReadOnly", false) || info.EditableStates < _infoProvider.CurrentRunState || valueChangePredicate is null || valueChangePredicate.Invoke(newValue); #else // Server has absolute authority. return true; #endif } public void Dispose() { if (!ModUtils.Threading.CheckIfClearAndSetBool(ref _isDisposed)) { return; } _infoProvider.Dispose(); _infoProvider = null; } private int _isDisposed; public bool IsDisposed { get => ModUtils.Threading.GetBool(ref _isDisposed); private set => ModUtils.Threading.SetBool(ref _isDisposed, value); } }