diff --git a/.gitignore b/.gitignore index fe2f9daa8..851678a91 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ [Ll]ibrary/ +[Uu]serSettings/ [Ll]ogs/ [Tt]emp/ [Oo]bj/ diff --git a/UltraStar Play/Assets/Common/Network/ConnectedClientHandler.cs b/UltraStar Play/Assets/Common/Network/ConnectedClientHandler.cs index e2701c4e8..e33efa9c6 100644 --- a/UltraStar Play/Assets/Common/Network/ConnectedClientHandler.cs +++ b/UltraStar Play/Assets/Common/Network/ConnectedClientHandler.cs @@ -10,8 +10,8 @@ public class ConnectedClientHandler : IDisposable public IPEndPoint ClientIpEndPoint { get; private set; } public string ClientName { get; private set; } + public string ClientId { get; private set; } public TcpListener MicTcpListener { get; private set; } - public string ClientId => ServerSideConnectRequestManager.GetClientId(ClientIpEndPoint); public int SampleRateHz => micSampleBuffer.Length; private bool isDisposed; @@ -31,15 +31,19 @@ public class ConnectedClientHandler : IDisposable private readonly Thread receiveDataThread; private readonly Thread clientStillAliveCheckThread; - public ConnectedClientHandler(ServerSideConnectRequestManager serverSideConnectRequestManager, IPEndPoint clientIpEndPoint, string clientName, int microphoneSampleRate) + public ConnectedClientHandler(ServerSideConnectRequestManager serverSideConnectRequestManager, IPEndPoint clientIpEndPoint, string clientName, string clientId, int microphoneSampleRate) { this.serverSideConnectRequestManager = serverSideConnectRequestManager; ClientIpEndPoint = clientIpEndPoint; ClientName = clientName; + ClientId = clientId; + if (ClientId.IsNullOrEmpty()) + { + throw new ArgumentException("Attempt to create ConnectedClientHandler without ClientId"); + } if (microphoneSampleRate <= 0) { - Debug.LogWarning("Attempt to create ConnectedClientHandler without microphoneSampleRate"); - return; + throw new ArgumentException("Attempt to create ConnectedClientHandler without microphoneSampleRate"); } micSampleBuffer = new float[microphoneSampleRate]; diff --git a/UltraStar Play/Assets/Common/Network/Dto/ConnectRequestDto.cs b/UltraStar Play/Assets/Common/Network/Dto/ConnectRequestDto.cs index e6952b68b..cd8aed877 100644 --- a/UltraStar Play/Assets/Common/Network/Dto/ConnectRequestDto.cs +++ b/UltraStar Play/Assets/Common/Network/Dto/ConnectRequestDto.cs @@ -2,5 +2,6 @@ { public int ProtocolVersion { get; set; } public string ClientName { get; set; } + public string ClientId { get; set; } public int MicrophoneSampleRate { get; set; } } diff --git a/UltraStar Play/Assets/Common/Network/Dto/ConnectResponseDto.cs b/UltraStar Play/Assets/Common/Network/Dto/ConnectResponseDto.cs index f47eab041..0a7a165e6 100644 --- a/UltraStar Play/Assets/Common/Network/Dto/ConnectResponseDto.cs +++ b/UltraStar Play/Assets/Common/Network/Dto/ConnectResponseDto.cs @@ -1,6 +1,7 @@ public class ConnectResponseDto : JsonSerializable { public string ClientName { get; set; } + public string ClientId { get; set; } public int MicrophonePort { get; set; } public string ErrorMessage { get; set; } public int HttpServerPort { get; set; } diff --git a/UltraStar Play/Assets/Common/Network/ServerSideConnectRequestManager.cs b/UltraStar Play/Assets/Common/Network/ServerSideConnectRequestManager.cs index 60544af12..5aa7e5e34 100644 --- a/UltraStar Play/Assets/Common/Network/ServerSideConnectRequestManager.cs +++ b/UltraStar Play/Assets/Common/Network/ServerSideConnectRequestManager.cs @@ -56,7 +56,7 @@ public static ServerSideConnectRequestManager Instance /** * This version number must to be increased when introducing breaking changes. */ - public const int ProtocolVersion = 1; + public const int ProtocolVersion = 2; private UdpClient serverUdpClient; private const int ConnectPortOnServer = 34567; @@ -155,7 +155,11 @@ private void HandleClientMessage(IPEndPoint clientIpEndPoint, string message) } if (connectRequestDto.ClientName.IsNullOrEmpty()) { - throw new ConnectRequestException("Malformed ConnectRequest: missing clientName."); + throw new ConnectRequestException("Malformed ConnectRequest: missing ClientName."); + } + if (connectRequestDto.ClientId.IsNullOrEmpty()) + { + throw new ConnectRequestException("Malformed ConnectRequest: missing ClientId."); } if (connectRequestDto.MicrophoneSampleRate > 0) @@ -182,6 +186,7 @@ private void HandleClientMessageWithNoMicrophone(IPEndPoint clientIpEndPoint, Co ConnectResponseDto connectResponseDto = new ConnectResponseDto { ClientName = connectRequestDto.ClientName, + ClientId = connectRequestDto.ClientId, HttpServerPort = httpServer.port, }; serverUdpClient.Send(connectResponseDto.ToJson(), clientIpEndPoint); @@ -189,12 +194,13 @@ private void HandleClientMessageWithNoMicrophone(IPEndPoint clientIpEndPoint, Co private void HandleClientMessageWithMicrophone(IPEndPoint clientIpEndPoint, ConnectRequestDto connectRequestDto) { - ConnectedClientHandler newConnectedClientHandler = RegisterClient(clientIpEndPoint, connectRequestDto.ClientName, connectRequestDto.MicrophoneSampleRate); + ConnectedClientHandler newConnectedClientHandler = RegisterClient(clientIpEndPoint, connectRequestDto.ClientName, connectRequestDto.ClientId, connectRequestDto.MicrophoneSampleRate); clientConnectedEventQueue.Enqueue(new ClientConnectionEvent(newConnectedClientHandler, true)); ConnectResponseDto connectResponseDto = new ConnectResponseDto { ClientName = connectRequestDto.ClientName, + ClientId = connectRequestDto.ClientId, HttpServerPort = httpServer.port, MicrophonePort = newConnectedClientHandler.MicTcpListener.GetPort(), }; @@ -235,16 +241,17 @@ public void RemoveConnectedClientHandler(ConnectedClientHandler connectedClientH private ConnectedClientHandler RegisterClient( IPEndPoint clientIpEndPoint, string clientName, + string clientId, int microphoneSampleRate) { // Dispose any currently registered client with the same IP-Address. - if (idToConnectedClientMap.TryGetValue(GetClientId(clientIpEndPoint), out ConnectedClientHandler existingConnectedClientHandler)) + if (idToConnectedClientMap.TryGetValue(clientId, out ConnectedClientHandler existingConnectedClientHandler)) { existingConnectedClientHandler.Dispose(); } - ConnectedClientHandler connectedClientHandler = new ConnectedClientHandler(this, clientIpEndPoint, clientName, microphoneSampleRate); - idToConnectedClientMap[GetClientId(clientIpEndPoint)] = connectedClientHandler; + ConnectedClientHandler connectedClientHandler = new ConnectedClientHandler(this, clientIpEndPoint, clientName, clientId, microphoneSampleRate); + idToConnectedClientMap[clientId] = connectedClientHandler; Debug.Log("New number of connected clients: " + idToConnectedClientMap.Count); @@ -260,9 +267,4 @@ public static bool TryGetConnectedClientHandler(string clientIpEndPointId, out C { return idToConnectedClientMap.TryGetValue(clientIpEndPointId, out connectedClientHandler); } - - public static string GetClientId(IPEndPoint clientIpEndPoint) - { - return clientIpEndPoint.Address.ToString(); - } } diff --git a/UltraStar Play/Assets/Common/Network/UltraStarPlayHttpServer.cs b/UltraStar Play/Assets/Common/Network/UltraStarPlayHttpServer.cs index 29f7b9490..039a5b7ca 100644 --- a/UltraStar Play/Assets/Common/Network/UltraStarPlayHttpServer.cs +++ b/UltraStar Play/Assets/Common/Network/UltraStarPlayHttpServer.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Net; using System.Net.Http; +using System.Net.NetworkInformation; using SimpleHttpServerForUnity; public class UltraStarPlayHttpServer : HttpServer @@ -19,7 +20,7 @@ protected override void Awake() return; } - host = IpAddressUtils.GetIpAddress(AddressFamily.IPv4); + host = IpAddressUtils.GetIpAddress(AddressFamily.IPv4, NetworkInterfaceType.Wireless80211); NoEndpointFoundCallback = SendNoEndpointFound; StartHttpListener(); diff --git a/UltraStar Play/Assets/Common/UI/ContextMenu/AbstractContextMenuHandler.cs b/UltraStar Play/Assets/Common/UI/ContextMenu/AbstractContextMenuHandler.cs index 2853dbab1..c5f530adb 100644 --- a/UltraStar Play/Assets/Common/UI/ContextMenu/AbstractContextMenuHandler.cs +++ b/UltraStar Play/Assets/Common/UI/ContextMenu/AbstractContextMenuHandler.cs @@ -48,15 +48,14 @@ private RectTransform RectTransform protected abstract void FillContextMenu(ContextMenu contextMenu); - private readonly List disposables = new List(); - public bool IsDrag { get; private set; } private Vector2 dragStartPosition; protected void Start() { - disposables.Add(InputManager.GetInputAction(R.InputActions.usplay_openContextMenu).PerformedAsObservable() - .Subscribe(CheckOpenContextMenuFromInputAction)); + InputManager.GetInputAction(R.InputActions.usplay_openContextMenu).PerformedAsObservable() + .Subscribe(CheckOpenContextMenuFromInputAction) + .AddTo(gameObject); } protected virtual void CheckOpenContextMenuFromInputAction(InputAction.CallbackContext context) @@ -106,11 +105,6 @@ private ContextMenu GetContextMenuPrefab() return UiManager.Instance.contextMenuPrefab; } - private void OnDestroy() - { - disposables.ForEach(it => it.Dispose()); - } - public void OnBeginDrag(PointerEventData eventData) { dragStartPosition = eventData.position; diff --git a/UltraStar Play/Assets/Common/UI/ContextMenu/ContextMenu.cs b/UltraStar Play/Assets/Common/UI/ContextMenu/ContextMenu.cs index 8afaf6b8a..1054dafc1 100644 --- a/UltraStar Play/Assets/Common/UI/ContextMenu/ContextMenu.cs +++ b/UltraStar Play/Assets/Common/UI/ContextMenu/ContextMenu.cs @@ -18,8 +18,6 @@ static void Init() public ContextMenuItem contextMenuItemPrefab; public ContextMenuSeparator contextMenuSeparatorPrefab; - private readonly List disposables = new List(); - private bool wasNoButtonOrTouchPressed; public static List OpenContextMenus { get; private set; } = new List(); @@ -48,7 +46,7 @@ protected override void Awake() transform.DestroyAllDirectChildren(); // Close with next click or tap - disposables.Add(InputManager.GetInputAction(R.InputActions.usplay_closeContextMenu).PerformedAsObservable() + InputManager.GetInputAction(R.InputActions.usplay_closeContextMenu).PerformedAsObservable() .Subscribe(context => { // Only close when the mouse / touchscreen has been fully released in the mean time. @@ -66,7 +64,8 @@ protected override void Awake() } CloseContextMenu(); - })); + }) + .AddTo(gameObject); } private void Start() @@ -121,8 +120,6 @@ public void CloseContextMenu() private void OnDestroy() { - disposables.ForEach(it => it.Dispose()); - // Remove this ContextMenu from the list of opened ContextMenus only after all Input has been released // to avoid triggering additional actions (e.g. onClick of button). if (CoroutineManager.Instance != null) diff --git a/UltraStar Play/Assets/Common/UI/Dialogs/QuestionDialog.cs b/UltraStar Play/Assets/Common/UI/Dialogs/QuestionDialog.cs index 27519b8e6..296d819f1 100644 --- a/UltraStar Play/Assets/Common/UI/Dialogs/QuestionDialog.cs +++ b/UltraStar Play/Assets/Common/UI/Dialogs/QuestionDialog.cs @@ -16,8 +16,6 @@ public class QuestionDialog : Dialog public bool noOnEscape = true; public bool focusYesOnStart = true; - private readonly List disposables = new List(); - private void Start() { yesButton.OnClickAsObservable().Subscribe(_ => @@ -38,14 +36,14 @@ private void Start() if (noOnEscape) { - disposables.Add(InputManager.GetInputAction(R.InputActions.usplay_back).PerformedAsObservable(5) - .Subscribe(OnBack)); + InputManager.GetInputAction(R.InputActions.usplay_back).PerformedAsObservable(5) + .Subscribe(OnBack) + .AddTo(gameObject); } } public void Close() { - disposables.ForEach(it => it.Dispose()); Destroy(gameObject); } diff --git a/UltraStar Play/Assets/Common/UI/Dialogs/WarningDialog.cs b/UltraStar Play/Assets/Common/UI/Dialogs/WarningDialog.cs index 29b1983ea..d57d25d60 100644 --- a/UltraStar Play/Assets/Common/UI/Dialogs/WarningDialog.cs +++ b/UltraStar Play/Assets/Common/UI/Dialogs/WarningDialog.cs @@ -10,8 +10,6 @@ public class WarningDialog : Dialog public bool focusOkButtonOnStart = true; - private readonly List disposables = new List(); - void Start() { okButton.OnClickAsObservable().Subscribe(_ => Close()); @@ -20,13 +18,13 @@ void Start() okButton.Select(); } - disposables.Add(InputManager.GetInputAction(R.InputActions.usplay_back).PerformedAsObservable(6) - .Subscribe(OnBack)); + InputManager.GetInputAction(R.InputActions.usplay_back).PerformedAsObservable(6) + .Subscribe(OnBack) + .AddTo(gameObject); } public void Close() { - disposables.ForEach(it => it.Dispose()); Destroy(gameObject); } diff --git a/UltraStar Play/Assets/Common/UI/Drag/AbstractDragHandler.cs b/UltraStar Play/Assets/Common/UI/Drag/AbstractDragHandler.cs index cfe5f356f..983265cb5 100644 --- a/UltraStar Play/Assets/Common/UI/Drag/AbstractDragHandler.cs +++ b/UltraStar Play/Assets/Common/UI/Drag/AbstractDragHandler.cs @@ -30,18 +30,17 @@ abstract public class AbstractDragHandler : MonoBehaviour, INeedInjection public RectTransform targetRectTransform; - private readonly List disposables = new List(); - protected virtual void Start() { - disposables.Add(InputManager.GetInputAction(R.InputActions.usplay_back).PerformedAsObservable(10) + InputManager.GetInputAction(R.InputActions.usplay_back).PerformedAsObservable(10) .Where(_ => IsDragging) .Subscribe(_ => { CancelDrag(); // Cancel other callbacks. To do so, this subscription has a higher priority. InputManager.GetInputAction(R.InputActions.usplay_back).CancelNotifyForThisFrame(); - })); + }) + .AddTo(gameObject); } public void AddListener(IDragListener listener) @@ -121,11 +120,6 @@ private void NotifyListeners(Action> action, bool includeCa } } - private void OnDestroy() - { - disposables.ForEach(it => it.Dispose()); - } - abstract protected EVENT CreateDragEventStart(PointerEventData eventData); abstract protected EVENT CreateDragEvent(PointerEventData eventData, EVENT dragStartEvent); diff --git a/UltraStar Play/Assets/Editor/BuildInfoGenerator.cs b/UltraStar Play/Assets/Editor/BuildInfoGenerator.cs index bfe81fc2b..f1277656d 100644 --- a/UltraStar Play/Assets/Editor/BuildInfoGenerator.cs +++ b/UltraStar Play/Assets/Editor/BuildInfoGenerator.cs @@ -1,7 +1,6 @@ using System; using System.Globalization; using System.IO; -using System.Text.RegularExpressions; using UnityEditor; using UnityEditor.Build; using UnityEditor.Build.Reporting; @@ -9,7 +8,9 @@ // Fills a file with build information before Unity performs the actual build. public class BuildInfoGenerator : IPreprocessBuildWithReport { + public static readonly string versionPropertyName = "release"; public static readonly string timeStampPropertyName = "build_timestamp"; + public static readonly string commitShortHashPropertyName = "commit_hash"; public static readonly string versionFile = "Assets/VERSION.txt"; public int callbackOrder @@ -28,14 +29,26 @@ public void OnPreprocessBuild(BuildReport report) private void UpdateVersionFile() { string timeStamp = DateTime.Now.ToString("yyMMddHHmm", CultureInfo.InvariantCulture); + string commitShortHash = GitUtils.GetCurrentCommitShortHash(); + string[] versionFileLines = File.ReadAllLines(versionFile); for (int i = 0; i < versionFileLines.Length; i++) { string line = versionFileLines[i]; + if (line.StartsWith(versionPropertyName, true, CultureInfo.InvariantCulture)) + { + versionFileLines[i] = $"{versionPropertyName} = {PlayerSettings.bundleVersion}"; + } + if (line.StartsWith(timeStampPropertyName, true, CultureInfo.InvariantCulture)) { versionFileLines[i] = $"{timeStampPropertyName} = {timeStamp}"; } + + if (line.StartsWith(commitShortHashPropertyName, true, CultureInfo.InvariantCulture)) + { + versionFileLines[i] = $"{commitShortHashPropertyName} = {commitShortHash}"; + } } File.WriteAllLines(versionFile, versionFileLines); // Unity needs a hint that this asset has changed. diff --git a/UltraStar Play/Assets/Editor/GitUtils.cs b/UltraStar Play/Assets/Editor/GitUtils.cs new file mode 100644 index 000000000..7f7f37620 --- /dev/null +++ b/UltraStar Play/Assets/Editor/GitUtils.cs @@ -0,0 +1,67 @@ +using System; +using System.Diagnostics; +using System.Linq; +using UnityEditor.Build; +using Debug = UnityEngine.Debug; + +public static class GitUtils +{ + // Original implementation from https://www.stewmcc.com/post/git-commands-from-unity/ + public static string RunGitCommand(string gitCommand) + { + // Set up our processInfo to run the git command and log to output and errorOutput. + ProcessStartInfo processInfo = new ProcessStartInfo("git", @gitCommand) + { + CreateNoWindow = true, // We want no visible pop-ups + UseShellExecute = false, // Allows us to redirect input, output and error streams + RedirectStandardOutput = true, // Allows us to read the output stream + RedirectStandardError = true // Allows us to read the error stream + }; + + // Set up the Process + Process process = new Process {StartInfo = processInfo}; + + try + { + // Try to start it, catching any exceptions if it fails + process.Start(); + } + catch (Exception e) + { + // For now just assume its failed cause it can't find git. + Debug.LogException(e); + Debug.LogError("Git is not set-up correctly, required to be on PATH, and to be a git project."); + return "git-error"; + } + + // Read the results back from the process so we can get the output and check for errors + string output = process.StandardOutput.ReadToEnd(); + string errorOutput = process.StandardError.ReadToEnd(); + + process.WaitForExit(); // Make sure we wait till the process has fully finished. + process.Close(); // Close the process ensuring it frees it resources. + + // Check for failure due to no git setup in the project itself or other fatal errors from git. + if (output.IsNullOrEmpty() || output.Contains("fatal")) + { + throw new BuildFailedException("Command: git " + @gitCommand + " Failed\n" + output + errorOutput); + } + + // Log any errors. + if (errorOutput != "") + { + Debug.LogError("Git Error: " + errorOutput); + } + + return output; + } + + public static string GetCurrentCommitShortHash() + { + string result = RunGitCommand("rev-parse --short --verify HEAD"); + // Clean up whitespace around hash. (seems to just be the way this command returns :/ ) + result = string.Join("", result.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries)); + Debug.Log("Current commit short hash: " + result); + return result; + } +} diff --git a/UltraStar Play/Assets/Editor/GitUtils.cs.meta b/UltraStar Play/Assets/Editor/GitUtils.cs.meta new file mode 100644 index 000000000..1ec20742c --- /dev/null +++ b/UltraStar Play/Assets/Editor/GitUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fee62f40db3d66e448a92efd6c59266d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UltraStar Play/Assets/Plugins/SimpleHttpServerForUnity/IpAddressUtils.cs b/UltraStar Play/Assets/Plugins/SimpleHttpServerForUnity/IpAddressUtils.cs index c7617ef71..23cce560c 100644 --- a/UltraStar Play/Assets/Plugins/SimpleHttpServerForUnity/IpAddressUtils.cs +++ b/UltraStar Play/Assets/Plugins/SimpleHttpServerForUnity/IpAddressUtils.cs @@ -1,14 +1,16 @@ -using System.Net.NetworkInformation; +using System.Collections.Generic; +using System.Linq; +using System.Net.NetworkInformation; using System.Net.Sockets; namespace SimpleHttpServerForUnity { -// https://stackoverflow.com/questions/51975799/how-to-get-ip-address-of-device-in-unity-2018 + // https://stackoverflow.com/questions/51975799/how-to-get-ip-address-of-device-in-unity-2018 public class IpAddressUtils { - public static string GetIpAddress(AddressFamily addressFamily) + public static string GetIpAddress(AddressFamily addressFamily, params NetworkInterfaceType[] networkInterfaceTypes) { - // Return null if AddressFamily is Ipv6 but Os does not support it + // Return null if AddressFamily is Ipv6 but OS does not support it if (addressFamily == AddressFamily.IPv6 && !Socket.OSSupportsIPv6) { return null; @@ -18,11 +20,8 @@ public static string GetIpAddress(AddressFamily addressFamily) foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces()) { #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN - NetworkInterfaceType type1 = NetworkInterfaceType.Wireless80211; - NetworkInterfaceType type2 = NetworkInterfaceType.Ethernet; - - if ((item.NetworkInterfaceType == type1 || item.NetworkInterfaceType == type2) && - item.OperationalStatus == OperationalStatus.Up) + if (networkInterfaceTypes.Contains(item.NetworkInterfaceType) + && item.OperationalStatus == OperationalStatus.Up) #endif { foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses) diff --git a/UltraStar Play/Assets/Scenes/Main/MainSceneUi.uxml b/UltraStar Play/Assets/Scenes/Main/MainSceneUi.uxml index 042cb5cc6..c604f4ad1 100644 --- a/UltraStar Play/Assets/Scenes/Main/MainSceneUi.uxml +++ b/UltraStar Play/Assets/Scenes/Main/MainSceneUi.uxml @@ -1,11 +1,11 @@