diff --git a/NebulaModel/MultiplayerOptions.cs b/NebulaModel/MultiplayerOptions.cs index a7b179ab8..5a26ecb8b 100644 --- a/NebulaModel/MultiplayerOptions.cs +++ b/NebulaModel/MultiplayerOptions.cs @@ -1,4 +1,5 @@ -using NebulaAPI; +using BepInEx.Configuration; +using NebulaAPI; using NebulaModel.Attributes; using NebulaModel.DataStructures; using NebulaModel.Utils; @@ -60,6 +61,10 @@ public class MultiplayerOptions : ICloneable [Description("Configure which type of IP should be used by Discord RPC")] public IPUtils.IPConfiguration IPConfiguration { get; set; } + [DisplayName("Cleanup inactive sessions"), Category("Network")] + [Description("If disabled the underlying networking library will not cleanup inactive connections. This might solve issues with clients randomly disconnecting and hosts having a 'System.ObjectDisposedException'.")] + public bool CleanupInactiveSessions { get; set; } = false; + [DisplayName("Show Lobby Hints")] public bool ShowLobbyHints { get; set; } = true; @@ -89,6 +94,10 @@ public bool StreamerMode { } } + [DisplayName("Chat Hotkey"), Category("Chat")] + [Description("Keyboard shortcut to toggle the chat window")] + public KeyboardShortcut ChatHotkey { get; set; } = new KeyboardShortcut(KeyCode.BackQuote, KeyCode.LeftAlt); + [DisplayName("Auto Open Chat"), Category("Chat")] [Description("Auto open chat window when receiving message from other players")] public bool AutoOpenChat { get; set; } = true; @@ -106,11 +115,12 @@ public bool StreamerMode { public ChatSize DefaultChatSize { get; set; } = ChatSize.Medium; [DisplayName("Notification duration"), Category("Chat")] + [Description("How long should the active message stay on the screen in seconds")] public int NotificationDuration { get; set; } = 15; - [DisplayName("Cleanup inactive sessions"), Category("Network")] - [Description("If disabled the underlying networking library will not cleanup inactive connections. This might solve issues with clients randomly disconnecting and hosts having a 'System.ObjectDisposedException'.")] - public bool CleanupInactiveSessions { get; set; } = true; + [DisplayName("Chat Window Opacity"), Category("Chat")] + [UIRange(0f, 1.0f, true)] + public float ChatWindowOpacity { get; set; } = 0.8f; // Detail function group buttons public bool PowerGridEnabled { get; set; } = false; diff --git a/NebulaPatcher/MonoBehaviours/NebulaBootstrapper.cs b/NebulaPatcher/MonoBehaviours/NebulaBootstrapper.cs index 333091257..98043f605 100644 --- a/NebulaPatcher/MonoBehaviours/NebulaBootstrapper.cs +++ b/NebulaPatcher/MonoBehaviours/NebulaBootstrapper.cs @@ -1,5 +1,4 @@ -using CommonAPI.Systems; -using NebulaWorld; +using NebulaWorld; using UnityEngine; namespace NebulaPatcher.MonoBehaviours diff --git a/NebulaPatcher/NebulaPlugin.cs b/NebulaPatcher/NebulaPlugin.cs index 072d23552..e7c1e4bfa 100644 --- a/NebulaPatcher/NebulaPlugin.cs +++ b/NebulaPatcher/NebulaPlugin.cs @@ -1,6 +1,4 @@ using BepInEx; -using CommonAPI; -using CommonAPI.Systems; using HarmonyLib; using NebulaAPI; using NebulaModel.Logger; @@ -20,8 +18,7 @@ namespace NebulaPatcher { [BepInPlugin(PluginInfo.PLUGIN_ID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)] - [BepInDependency(CommonAPIPlugin.GUID)] - [CommonAPISubmoduleDependency(nameof(ProtoRegistry), nameof(CustomKeyBindSystem))] + [BepInDependency("dsp.common - api.CommonAPI", BepInDependency.DependencyFlags.SoftDependency)] public class NebulaPlugin : BaseUnityPlugin, IMultiplayerMod { static int command_ups = 0; @@ -176,7 +173,6 @@ private static void Initialize() { InitPatches(); AddNebulaBootstrapper(); - RegisterKeyBinds(); DiscordManager.Setup(ActivityManager_OnActivityJoin); } @@ -285,19 +281,6 @@ private void Update() } } - private static void RegisterKeyBinds() - { - CustomKeyBindSystem.RegisterKeyBind(new BuiltinKey - { - id = 212, - key = new CombineKey((int)KeyCode.BackQuote, CombineKey.ALT_COMB, ECombineKeyAction.OnceClick, false), - conflictGroup = 2052, - name = "NebulaChatWindow", - canOverride = true - }); - ProtoRegistry.RegisterString("KEYNebulaChatWindow", "Show or Hide Chat Window"); - } - private static void InitPatches() { Log.Info("Patching Dyson Sphere Program..."); diff --git a/NebulaPatcher/Patches/Dynamic/UIOptionWindow_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIOptionWindow_Patch.cs index c68ba5d0f..5117ecc29 100644 --- a/NebulaPatcher/Patches/Dynamic/UIOptionWindow_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/UIOptionWindow_Patch.cs @@ -1,4 +1,5 @@ -using HarmonyLib; +using BepInEx.Configuration; +using HarmonyLib; using NebulaModel; using NebulaModel.Attributes; using NebulaModel.Logger; @@ -165,7 +166,6 @@ public static void _OnCreate_Postfix(UIOptionWindow __instance) checkboxTemplate = contentTemplate.Find("fullscreen").GetComponent(); comboBoxTemplate = contentTemplate.Find("resolution").GetComponent(); sliderTemplate = contentTemplate.Find("dofblur").GetComponent(); - inputTemplate = Object.Instantiate(checkboxTemplate, listContent, false); Object.Destroy(inputTemplate.Find("CheckBox").gameObject); RectTransform inputField = Object.Instantiate(UIRoot.instance.saveGameWindow.transform.Find("input-filename/InputField").GetComponent(), inputTemplate, false); @@ -305,6 +305,10 @@ private static void AddMultiplayerOptionsProperties() { CreateEnumControl(displayAttr, descriptionAttr, prop, anchorPosition, container); } + else if (prop.PropertyType == typeof(BepInEx.Configuration.KeyboardShortcut)) + { + CreateHotkeyControl(displayAttr, descriptionAttr, prop, anchorPosition, container); + } else { Log.Warn($"MultiplayerOption property \"${prop.Name}\" of type \"{prop.PropertyType}\" not supported."); @@ -396,7 +400,7 @@ private static void CreateNumberControl(DisplayNameAttribute control, Descriptio { try { - TypeConverter converter = TypeDescriptor.GetConverter(prop.PropertyType); + System.ComponentModel.TypeConverter converter = TypeDescriptor.GetConverter(prop.PropertyType); System.IComparable value = (System.IComparable)converter.ConvertFromString(str); if (rangeAttr != null) @@ -479,6 +483,48 @@ private static void CreateEnumControl(DisplayNameAttribute control, DescriptionA }; } + private static void CreateHotkeyControl(DisplayNameAttribute control, DescriptionAttribute descriptionAttr, PropertyInfo prop, Vector2 anchorPosition, Transform container) + { + UICharacterLimitAttribute characterLimitAttr = prop.GetCustomAttribute(); + UIContentTypeAttribute contentTypeAttr = prop.GetCustomAttribute(); + + RectTransform element = Object.Instantiate(inputTemplate, container, false); + SetupUIElement(element, control, descriptionAttr, prop, anchorPosition); + + InputField input = element.GetComponentInChildren(); + if (characterLimitAttr != null) + { + input.characterLimit = characterLimitAttr.Max; + } + if (contentTypeAttr != null) + { + input.contentType = contentTypeAttr.ContentType; + } + + input.onValueChanged.RemoveAllListeners(); + input.onValueChanged.AddListener((value) => { + if (!string.IsNullOrEmpty(value)) + { + KeyboardShortcut hotkey = KeyboardShortcut.Deserialize(value); + if (hotkey.Equals(KeyboardShortcut.Empty)) + { + // Show text color in red when the shortcut is not valid + input.textComponent.color = Color.red; + } + else + { + input.textComponent.color = Color.white; + prop.SetValue(tempMultiplayerOptions, hotkey, null); + } + } + }); + + tempToUICallbacks[prop.Name] = () => + { + input.text = ((KeyboardShortcut)prop.GetValue(tempMultiplayerOptions, null)).ToString(); + }; + } + private static void SetupUIElement(RectTransform element, DisplayNameAttribute display, DescriptionAttribute descriptionAttr, PropertyInfo prop, Vector2 anchorPosition) { element.gameObject.SetActive(true); diff --git a/NebulaWorld/MonoBehaviours/Local/Chat/ChatManager.cs b/NebulaWorld/MonoBehaviours/Local/Chat/ChatManager.cs index 8186390ad..16def4746 100644 --- a/NebulaWorld/MonoBehaviours/Local/Chat/ChatManager.cs +++ b/NebulaWorld/MonoBehaviours/Local/Chat/ChatManager.cs @@ -1,18 +1,18 @@ -using CommonAPI; -using CommonAPI.Systems; -using NebulaModel; +using NebulaModel; using NebulaModel.DataStructures; using NebulaModel.Logger; using NebulaModel.Packets.Players; using NebulaModel.Utils; using System; using UnityEngine; +using UnityEngine.UI; namespace NebulaWorld.MonoBehaviours.Local { public class ChatManager : MonoBehaviour { private ChatWindow chatWindow; + private Image backgroundImage; public static ChatManager Instance; private void Awake() @@ -36,7 +36,11 @@ private void Awake() trans.sizeDelta = defaultSize; trans.anchoredPosition = defaultPos; - chatGo.GetComponent().minSize = ChatUtils.GetDefaultSize(ChatSize.Small); + // TODO: Fix ChatV2.prefab to get rid of warnings + GameObject backgroundGo = chatGo.transform.Find("Main/background").gameObject; + DestroyImmediate(backgroundGo.GetComponent()); + backgroundImage = backgroundGo.AddComponent(); + backgroundImage.color = new Color(0f, 0f, 0f, options.ChatWindowOpacity); } chatWindow = chatGo.transform.GetComponentInChildren(); @@ -60,11 +64,12 @@ public static void UpdateChatPosition() RectTransform trans = (RectTransform)Instance.chatWindow.transform; trans.anchoredPosition = defaultPos; trans.sizeDelta = defaultSize; + Instance.backgroundImage.color = new Color(0f, 0f, 0f, options.ChatWindowOpacity); } void Update() { - if (CustomKeyBindSystem.GetKeyBind("NebulaChatWindow").keyValue) + if (Config.Options.ChatHotkey.IsDown()) { chatWindow.Toggle(); }