public static bool LoadOptions() { Options = new MultiplayerOptions(); try { configFile = new ConfigFile(Path.Combine(Paths.ConfigPath, OPTION_SAVE_FILE), true); List <PropertyInfo> properties = AccessTools.GetDeclaredProperties(typeof(MultiplayerOptions)); MethodInfo configBindMethod = typeof(ConfigFile) .GetMethods() .Where(m => m.Name == nameof(ConfigFile.Bind)) .First(m => m.IsGenericMethod && m.GetParameters().Length == 4); foreach (PropertyInfo prop in properties) { object entry = configBindMethod.MakeGenericMethod(prop.PropertyType).Invoke(configFile, new object[] { SECTION_NAME, prop.Name, prop.GetValue(Options), null }); Type entryType = typeof(ConfigEntry <>).MakeGenericType(prop.PropertyType); prop.SetValue(Options, AccessTools.Property(entryType, "Value").GetValue(entry)); } } catch (Exception e) { Log.Error($"Could not load {OPTION_SAVE_FILE}", e); return(false); } return(true); }
public static void FindUnpatchedInType(Type type, string[] unsupportedTypes, List <string> systemRngLog, List <string> unityRngLog, List <string> logAllClasses = null) { // Don't mind all the try/catch blocks, I went for maximum safety try { if (unsupportedTypes.Any(t => type.Namespace != null && (type.Namespace == t || type.Namespace.StartsWith($"{t}.")))) { return; } } catch (Exception) { // ignored } if (logAllClasses != null) { lock (logAllClasses) logAllClasses.Add(type.FullName); } try { // Get all methods, constructors, getters, and setters (everything that should have IL instructions) var methods = AccessTools.GetDeclaredMethods(type).Cast <MethodBase>() .Concat(AccessTools.GetDeclaredConstructors(type)) .Concat(AccessTools.GetDeclaredProperties(type).SelectMany(p => new[] { p.GetGetMethod(true), p.GetSetMethod(true) }).Where(p => p != null)); foreach (var method in methods) { try { MpCompat.harmony.Patch(method, transpiler: new HarmonyMethod(typeof(DebugActions), nameof(FindRng))); } catch (Exception e) when((e?.InnerException ?? e) is PatchingCancelledException cancelled) { if (cancelled.foundSystemRng) { lock (systemRngLog) systemRngLog.Add($"{type.FullName}:{method.Name}"); } if (cancelled.foundUnityRng) { lock (unityRngLog) unityRngLog.Add($"{type.FullName}:{method.Name}"); } } catch (Exception) { // ignored } } } catch (Exception) { // ignored } }
public static void TempOptionToUI_Postfix() { List <PropertyInfo> properties = AccessTools.GetDeclaredProperties(typeof(MultiplayerOptions)); foreach (var prop in properties) { if (tempToUICallbacks.TryGetValue(prop.Name, out var callback)) { callback(); } } }
public static bool SaveOptions() { try { List <PropertyInfo> properties = AccessTools.GetDeclaredProperties(typeof(MultiplayerOptions)); foreach (PropertyInfo prop in properties) { ConfigDefinition key = new ConfigDefinition(SECTION_NAME, prop.Name); configFile[key].BoxedValue = prop.GetValue(Options); } configFile.Save(); } catch (Exception e) { Log.Error($"Could not load {OPTION_SAVE_FILE}", e); return(false); } return(true); }
private static void AddMultiplayerOptionsProperties(RectTransform container) { List <PropertyInfo> properties = AccessTools.GetDeclaredProperties(typeof(MultiplayerOptions)); Vector2 anchorPosition = new Vector2(30, -20); foreach (PropertyInfo prop in properties) { DisplayNameAttribute displayAttr = prop.GetCustomAttribute <DisplayNameAttribute>(); DescriptionAttribute descriptionAttr = prop.GetCustomAttribute <DescriptionAttribute>(); if (displayAttr != null) { if (prop.PropertyType == typeof(bool)) { CreateBooleanControl(displayAttr, descriptionAttr, prop, anchorPosition, container); } else if (prop.PropertyType == typeof(int) || prop.PropertyType == typeof(float) || prop.PropertyType == typeof(ushort)) { CreateNumberControl(displayAttr, descriptionAttr, prop, anchorPosition, container); } else if (prop.PropertyType == typeof(string)) { CreateStringControl(displayAttr, descriptionAttr, prop, anchorPosition, container); } else if (prop.PropertyType.IsEnum) { CreateEnumControl(displayAttr, descriptionAttr, prop, anchorPosition, container); } else { Log.Warn($"MultiplayerOption property \"${prop.Name}\" of type \"{prop.PropertyType}\" not supported."); continue; } anchorPosition = new Vector2(anchorPosition.x, anchorPosition.y - 40); } } container.sizeDelta = new Vector2(container.sizeDelta.x, -anchorPosition.y + 40); }