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
}