using UnityEngine; using Unity.Netcode; using Unity.Collections; using System; using UnityEngine.XR.Interaction.Toolkit.Samples.SpatialKeyboard; #if UNITY_EDITOR using UnityEditor; #endif namespace XRMultiplayer { /// /// Represents a message board that allows players to submit and display messages in a networked environment. /// public class NetworkMessageBoard : NetworkBehaviour { /// /// The prefab for the message text. /// [SerializeField] GameObject m_MessagePrefab; /// /// The transform that contains the viewport for the messages. /// [SerializeField] Transform m_ContentViewport; /// /// The maximum number of messages that can be displayed. /// [SerializeField] int m_MaxMessageCount = 100; /// /// The maximum number of characters that can be displayed in a message. /// [SerializeField] int m_MaxCharacterCount = 256; /// /// The list of current messages. /// NetworkList messageList; /// void Start() { XRINetworkGameManager.Connected.Subscribe(ConnectedToNetwork); messageList = new NetworkList(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); } /// /// Called when the network connection status changes. /// /// Indicates whether the player is connected to the network. void ConnectedToNetwork(bool connected) { if (!connected) { foreach (Transform t in m_ContentViewport) { Destroy(t.gameObject); } } } // Called from XRIKeyboardDisplay public void ToggleKeyboardOpen(bool toggle) { GlobalNonNativeKeyboard.instance.keyboard.closeOnSubmit = !toggle; } /// public override void OnNetworkSpawn() { base.OnNetworkSpawn(); if (IsServer) { messageList.Clear(); } foreach (FixedString512Bytes message in messageList) { CreateText(message.ToString()); } } /// /// Submits a text message locally. /// /// The text message to submit. public void SubmitTextLocal(string text) { if (string.IsNullOrEmpty(text) || string.IsNullOrWhiteSpace(text)) return; string textToSend = $"{XRINetworkPlayer.LocalPlayer.playerName}:

{text}"; if (textToSend.Length > m_MaxCharacterCount) { textToSend = textToSend.Substring(0, m_MaxCharacterCount); } FixedString512Bytes newText = new FixedString512Bytes(textToSend); SubmitMessageServerRpc(newText); } /// /// Submits a message to the server. /// /// The message to submit. [ServerRpc(RequireOwnership = false)] void SubmitMessageServerRpc(FixedString512Bytes text) { messageList.Add(text); if (messageList.Count > m_MaxMessageCount) { messageList.RemoveAt(0); } SubmitMessageClientRpc(text); } /// /// Submits a message to the clients. /// /// The message to submit. [ClientRpc] void SubmitMessageClientRpc(FixedString512Bytes text) { CreateText(text.ToString()); } /// /// Creates a text message and adds it to the message board. /// /// The text of the message. void CreateText(string text) { Instantiate(m_MessagePrefab, m_ContentViewport).GetComponent().SetMessage(text, DateTime.Now.ToString("h:mm tt")); // message.SetMessage(text, DateTime.Now.ToString("h:mm tt")); if (m_ContentViewport.childCount > m_MaxMessageCount) { Destroy(m_ContentViewport.GetChild(0).gameObject); } } } #if UNITY_EDITOR [CustomEditor(typeof(NetworkMessageBoard), true), CanEditMultipleObjects] public class NetworkMessageBoardEditor : Editor { [SerializeField, TextArea(10, 15)] string m_DebugText; public override void OnInspectorGUI() { base.OnInspectorGUI(); GUILayout.Space(10); GUILayout.Label("Debug Area", EditorStyles.boldLabel); GUI.enabled = XRINetworkGameManager.Connected.Value; if(!XRINetworkGameManager.Connected.Value) { GUILayout.Label("Connect to a network to submit messages.", EditorStyles.helpBox); } else { GUILayout.Label("Debug Text"); m_DebugText = GUILayout.TextArea(m_DebugText); } if (GUILayout.Button("Submit Text Debug")) { ((NetworkMessageBoard)target).SubmitTextLocal(m_DebugText); } GUI.enabled = true; } } #endif }