public override void SetValueInConfig(string value) { var pluginConfig = BepInExUtils.GetDependentPlugins(true).First(x => x.Key == ModGUID).Value.Config; var entry = pluginConfig[Section, Key]; entry.BoxedValue = value; }
internal override string GetValueFromConfig() { var pluginConfig = BepInExUtils.GetDependentPlugins(true).First(x => x.Key == ModGUID).Value.Config; var entry = pluginConfig[Section, Key]; return((string)entry.BoxedValue); }
/// <summary> /// Unlock configuration entries. /// </summary> private void UnlockConfigurationEntries() { var loadedPlugins = BepInExUtils.GetDependentPlugins(true); foreach (var plugin in loadedPlugins) { foreach (var configDefinition in plugin.Value.Config.Keys) { var configEntry = plugin.Value.Config[configDefinition.Section, configDefinition.Key]; var configAttribute = (ConfigurationManagerAttributes)configEntry.Description.Tags .FirstOrDefault(x => x is ConfigurationManagerAttributes { IsAdminOnly: true });
internal void SynchronizeToServer() { // Lets compare and send to server, if applicable var loadedPlugins = BepInExUtils.GetDependentPlugins(); var valuesToSend = new List <Tuple <string, string, string, string> >(); foreach (var plugin in loadedPlugins) { foreach (var cd in plugin.Value.Config.Keys) { var cx = plugin.Value.Config[cd.Section, cd.Key]; if (cx.Description.Tags.Any(x => x is ConfigurationManagerAttributes && ((ConfigurationManagerAttributes)x).IsAdminOnly && ((ConfigurationManagerAttributes)x).UnlockSetting)) { var value = new Tuple <string, string, string, string>(plugin.Value.Info.Metadata.GUID, cd.Section, cd.Key, cx.GetSerializedValue()); valuesToSend.Add(value); } if (cx.SettingType == typeof(KeyCode)) { ZInput.instance.Setbutton(cd.Key + "!" + plugin.Value.Info.Metadata.GUID, (KeyCode)cx.BoxedValue); } } } // We need only changed values valuesToSend = valuesToSend.Where(x => !cachedConfigValues.Contains(x)).ToList(); // Send to server if (valuesToSend.Count > 0) { var zPackage = GenerateConfigZPackage(valuesToSend); // Send values to server if it isn't a local instance if (!ZNet.instance.IsLocalInstance()) { ZRoutedRpc.instance.InvokeRoutedRPC(ZNet.instance.GetServerPeer().m_uid, nameof(RPC_Jotunn_ApplyConfig), zPackage); } else { // If it is a local instance, send it to all connected peers foreach (var peer in ZNet.instance.m_peers) { ZRoutedRpc.instance.InvokeRoutedRPC(peer.m_uid, nameof(RPC_Jotunn_ApplyConfig), zPackage); } } } }
public override KeyCode GetValue() { // TODO: Get and parse value from input field var pluginConfig = BepInExUtils.GetDependentPlugins(true).First(x => x.Key == ModGUID).Value.Config; var entry = pluginConfig[Section, Key]; var temp = KeyCode.None; if (Enum.TryParse(gameObject.transform.Find("Button/Text").GetComponent <Text>().text, out temp)) { return(temp); } Logger.LogError($"Error parsing Keycode {gameObject.transform.Find("Button/Text").GetComponent<Text>().text}"); return(temp); }
private void AutomaticLocalizationLoading() { var jsonFormat = new HashSet <FileInfo>(); var unityFormat = new HashSet <FileInfo>(); // Json format community files foreach (var fileInfo in GetTranslationFiles(Paths.LanguageTranslationsFolder, CommunityTranslationFileName)) { jsonFormat.Add(fileInfo); } foreach (var fileInfo in GetTranslationFiles(Paths.LanguageTranslationsFolder, "*.json")) { jsonFormat.Add(fileInfo); } foreach (var fileInfo in GetTranslationFiles(Paths.LanguageTranslationsFolder, "*.language")) { unityFormat.Add(fileInfo); } foreach (var fileInfo in jsonFormat) { try { var mod = BepInExUtils.GetPluginInfoFromPath(fileInfo)?.Metadata; GetLocalization(mod ?? Main.Instance.Info.Metadata).AddFileByPath(fileInfo.FullName, true); } catch (Exception ex) { Logger.LogWarning($"Exception caught while loading localization file {fileInfo}: {ex}"); } } foreach (var fileInfo in unityFormat) { try { var mod = BepInExUtils.GetPluginInfoFromPath(fileInfo)?.Metadata; GetLocalization(mod ?? Main.Instance.Info.Metadata).AddFileByPath(fileInfo.FullName); } catch (Exception ex) { Logger.LogWarning($"Exception caught while loading localization file {fileInfo}: {ex}"); } } }
/// <summary> /// Get the CustomLocalization for your mod. /// Creates a new <see cref="CustomLocalization"/> if no localization was added before. /// </summary> /// <returns>Existing or newly created <see cref="CustomLocalization"/>.</returns> public CustomLocalization GetLocalization() { return(GetLocalization(BepInExUtils.GetSourceModMetadata())); }
/// <summary> /// Get a <see cref="CustomRPC"/> for your mod /// </summary> /// <param name="name">Unique name for your RPC</param> /// <param name="serverReceive">Delegate which gets called on client instances when packages are received</param> /// <param name="clientReceive">Delegate which gets called on server instances when packages are received</param> /// <returns>Existing or newly created <see cref="CustomRPC"/></returns> public CustomRPC AddRPC(string name, CoroutineHandler serverReceive, CoroutineHandler clientReceive) { return(AddRPC(BepInExUtils.GetSourceModMetadata(), name, serverReceive, clientReceive)); }
/// <summary> /// Create custom configuration tab /// </summary> private static void CreateModConfigTab() { bool anyConfig = BepInExUtils.GetDependentPlugins(true).Any(x => GetConfigurationEntries(x.Value).GroupBy(x => x.Key.Section).Any()); if (!anyConfig) { return; } // Hook SaveSettings to be notified when OK was pressed On.Settings.SaveSettings += Settings_SaveSettings; // Copy the Misc tab button var tabButtonCopy = Object.Instantiate(settingsRoot.transform.Find("panel/TabButtons/Misc").gameObject, settingsRoot.transform.Find("panel/TabButtons")); var tabHandler = settingsRoot.transform.Find("panel/TabButtons").GetComponent <TabHandler>(); // and set it's new property values tabButtonCopy.name = "ModConfig"; tabButtonCopy.transform.Find("Text").GetComponent <Text>().text = "ModConfig"; tabButtonCopy.transform.Find("Selected/Text (1)").GetComponent <Text>().text = "ModConfig"; // Rearrange/center settings tab buttons (Valheim had an offset to the right.....) var numChildren = settingsRoot.transform.Find("panel/TabButtons").childCount; var width = settingsRoot.transform.Find("panel/TabButtons").GetComponent <RectTransform>().rect.width; for (var i = 0; i < numChildren; i++) { settingsRoot.transform.Find("panel/TabButtons").GetChild(i).GetComponent <RectTransform>().anchoredPosition = new Vector2( (width - numChildren * 100f) / 2f + i * 100f + 50f, settingsRoot.transform.Find("panel/TabButtons").GetChild(i).GetComponent <RectTransform>().anchoredPosition.y); } // Add the tab var tab = settingsRoot.transform.Find("panel/Tabs").gameObject; // Create the content scroll view configTab = GUIManager.Instance.CreateScrollView(tab.transform, false, true, 8f, 10f, GUIManager.Instance.ValheimScrollbarHandleColorBlock, new Color(0, 0, 0, 1), tab.GetComponent <RectTransform>().rect.width - 50f, tab.GetComponent <RectTransform>().rect.height - 50f) .SetMiddleCenter(); configTab.name = "ModConfig"; // configure the ui group handler var groupHandler = configTab.AddComponent <UIGroupHandler>(); groupHandler.m_groupPriority = 10; groupHandler.m_canvasGroup = configTab.GetComponent <CanvasGroup>(); groupHandler.m_canvasGroup.ignoreParentGroups = true; groupHandler.m_canvasGroup.blocksRaycasts = true; groupHandler.Update(); // create ok and back button (just copy them from Controls tab) var ok = Object.Instantiate(settingsRoot.transform.Find("panel/Tabs/Controls/Ok").gameObject, configTab.transform); ok.GetComponent <RectTransform>().anchoredPosition = ok.GetComponent <RectTransform>().anchoredPosition - new Vector2(0, 25f); ok.GetComponent <Button>().onClick.AddListener(() => { Settings.instance.OnOk(); // After applying ingame values, lets synchronize any changed (and unlocked) values SynchronizationManager.Instance.SynchronizeToServer(); // remove reference to gameobject settingsRoot = null; configTab = null; }); var back = Object.Instantiate(settingsRoot.transform.Find("panel/Tabs/Controls/Back").gameObject, configTab.transform); back.GetComponent <RectTransform>().anchoredPosition = back.GetComponent <RectTransform>().anchoredPosition - new Vector2(0, 25f); back.GetComponent <Button>().onClick.AddListener(() => { Settings.instance.OnBack(); // remove reference to gameobject settingsRoot = null; configTab = null; }); // initially hide the configTab configTab.SetActive(false); // Add a new Tab to the TabHandler var newTab = new TabHandler.Tab(); newTab.m_default = false; newTab.m_button = tabButtonCopy.GetComponent <Button>(); newTab.m_page = configTab.GetComponent <RectTransform>(); newTab.m_onClick = new UnityEvent(); newTab.m_onClick.AddListener(() => { configTab.GetComponent <UIGroupHandler>().SetActive(true); configTab.SetActive(true); configTab.transform.Find("Scroll View").GetComponent <ScrollRect>().normalizedPosition = new Vector2(0, 1); }); // Add the onClick of the tabhandler to the tab button tabButtonCopy.GetComponent <Button>().onClick.AddListener(() => tabHandler.OnClick(newTab.m_button)); // and add the new Tab to the tabs list tabHandler.m_tabs.Add(newTab); var innerWidth = configTab.GetComponent <RectTransform>().rect.width - 25f; // Iterate over all dependent plugins (including Jotunn itself) foreach (var mod in BepInExUtils.GetDependentPlugins(true)) { // Create a header if there are any relevant configuration entries // TODO: dont count hidden ones if (GetConfigurationEntries(mod.Value).GroupBy(x => x.Key.Section).Any()) { // Create module header Text element var text = GUIManager.Instance.CreateText(mod.Key, configTab.transform.Find("Scroll View/Viewport/Content"), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0, 0), GUIManager.Instance.AveriaSerifBold, 20, Color.white, true, Color.black, configTab.GetComponent <RectTransform>().rect.width, 50, false); text.GetComponent <RectTransform>().pivot = new Vector2(0.5f, 0.5f); text.GetComponent <Text>().alignment = TextAnchor.MiddleCenter; text.AddComponent <LayoutElement>().preferredHeight = 40f; } // Iterate over all configuration entries (grouped by their sections) // TODO: again, don't show hidden ones, helper function! foreach (var kv in GetConfigurationEntries(mod.Value).GroupBy(x => x.Key.Section)) { // Create section header Text element var sectiontext = GUIManager.Instance.CreateText("Section " + kv.Key, configTab.transform.Find("Scroll View/Viewport/Content"), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0, 0), GUIManager.Instance.AveriaSerifBold, 16, GUIManager.Instance.ValheimOrange, true, Color.black, configTab.GetComponent <RectTransform>().rect.width, 30, false); sectiontext.SetMiddleCenter(); sectiontext.GetComponent <RectTransform>().anchoredPosition = new Vector2(0, 0); sectiontext.GetComponent <Text>().alignment = TextAnchor.MiddleCenter; sectiontext.AddComponent <LayoutElement>().preferredHeight = 30f; // Iterate over all entries of this section foreach (var entry in kv.OrderByDescending(x => { if (x.Value.Description.Tags.FirstOrDefault(y => y is ConfigurationManagerAttributes) is ConfigurationManagerAttributes cma) { return(cma.Order ?? 0); } return(0); }).ThenBy(x => x.Key.Key)) { // Create config entry // switch by type if (entry.Value.SettingType == typeof(bool)) { // Create toggle element var go = CreateToggleElement(configTab.transform.Find("Scroll View/Viewport/Content"), entry.Key.Key + ":", entry.Value.Description.Description, mod.Value.Info.Metadata.GUID, entry.Key.Section, entry.Key.Key, innerWidth); SetProperties(go.GetComponent <ConfigBoundBoolean>(), entry); } else if (entry.Value.SettingType == typeof(int)) { var description = entry.Value.Description.Description; if (entry.Value.Description.AcceptableValues != null) { description += Environment.NewLine + "(" + entry.Value.Description.AcceptableValues.ToDescriptionString().TrimStart('#').Trim() + ")"; } // Create input field int var go = CreateTextInputField(configTab.transform.Find("Scroll View/Viewport/Content"), entry.Key.Key + ":", description, mod.Value.Info.Metadata.GUID, entry.Key.Section, entry.Key.Key, innerWidth); go.AddComponent <ConfigBoundInt>().SetData(mod.Value.Info.Metadata.GUID, entry.Key.Section, entry.Key.Key); go.transform.Find("Input").GetComponent <InputField>().characterValidation = InputField.CharacterValidation.Integer; SetProperties(go.GetComponent <ConfigBoundInt>(), entry); go.transform.Find("Input").GetComponent <InputField>().onValueChanged.AddListener(x => { go.transform.Find("Input").GetComponent <InputField>().textComponent.color = go.GetComponent <ConfigBoundInt>().IsValid() ? Color.white : Color.red; }); } else if (entry.Value.SettingType == typeof(float)) { var description = entry.Value.Description.Description; if (entry.Value.Description.AcceptableValues != null) { description += Environment.NewLine + "(" + entry.Value.Description.AcceptableValues.ToDescriptionString().TrimStart('#').Trim() + ")"; } // Create input field float var go = CreateTextInputField(configTab.transform.Find("Scroll View/Viewport/Content"), entry.Key.Key + ":", description, mod.Value.Info.Metadata.GUID, entry.Key.Section, entry.Key.Key, innerWidth); go.AddComponent <ConfigBoundFloat>().SetData(mod.Value.Info.Metadata.GUID, entry.Key.Section, entry.Key.Key); go.transform.Find("Input").GetComponent <InputField>().characterValidation = InputField.CharacterValidation.Decimal; SetProperties(go.GetComponent <ConfigBoundFloat>(), entry); go.transform.Find("Input").GetComponent <InputField>().onValueChanged.AddListener(x => { go.transform.Find("Input").GetComponent <InputField>().textComponent.color = go.GetComponent <ConfigBoundFloat>().IsValid() ? Color.white : Color.red; }); } else if (entry.Value.SettingType == typeof(KeyCode)) { // Create key binder var go = CreateKeybindElement(configTab.transform.Find("Scroll View/Viewport/Content"), entry.Key.Key + ":", entry.Value.Description.Description, mod.Value.Info.Metadata.GUID, entry.Key.Section, entry.Key.Key, innerWidth); go.GetComponent <ConfigBoundKeyCode>().SetData(mod.Value.Info.Metadata.GUID, entry.Key.Section, entry.Key.Key); SetProperties(go.GetComponent <ConfigBoundKeyCode>(), entry); } else if (entry.Value.SettingType == typeof(string)) { // Create input field string var go = CreateTextInputField(configTab.transform.Find("Scroll View/Viewport/Content"), entry.Key.Key + ":", entry.Value.Description.Description, mod.Value.Info.Metadata.GUID, entry.Key.Section, entry.Key.Key, innerWidth); go.AddComponent <ConfigBoundString>().SetData(mod.Value.Info.Metadata.GUID, entry.Key.Section, entry.Key.Key); go.transform.Find("Input").GetComponent <InputField>().characterValidation = InputField.CharacterValidation.None; SetProperties(go.GetComponent <ConfigBoundString>(), entry); } } } } }
/// <summary> /// ctor automatically getting the SourceMod /// </summary> internal CustomEntity() { SourceMod = BepInExUtils.GetSourceModMetadata(); }