using System; using System.Collections.Generic; using Oculus.Platform.Models; using UnityEngine; using UnityEngine.UI; namespace Oculus.Platform.Samples.VrBoardGame { public class MatchmakingManager : MonoBehaviour { private enum MatchRoomState { None = 0, Queued = 1, Configuring = 2, MyTurn = 3, RemoteTurn = 4 } [SerializeField] private GameController m_gameController; [SerializeField] private Text m_matchButtonText; [SerializeField] private Text m_infoText; private const string POOL = "VR_BOARD_GAME_POOL"; private ulong m_matchRoom; private User m_remotePlayer; private float m_lastUpdateTime; private const float POLL_FREQUENCY = 30f; private MatchRoomState m_state; private void Start() { Matchmaking.SetMatchFoundNotificationCallback(MatchFoundCallback); Rooms.SetUpdateNotificationCallback(MatchmakingRoomUpdateCallback); TransitionToState(MatchRoomState.None); } private void Update() { MatchRoomState state = m_state; if ((state == MatchRoomState.Configuring || state == MatchRoomState.MyTurn || state == MatchRoomState.RemoteTurn) && 30f < Time.time - m_lastUpdateTime) { Debug.Log("Polling Room"); m_lastUpdateTime = Time.time; Rooms.Get(m_matchRoom).OnComplete(MatchmakingRoomUpdateCallback); } } public void MatchButtonPressed() { if (m_state == MatchRoomState.None) { TransitionToState(MatchRoomState.Queued); } else { TransitionToState(MatchRoomState.None); } } public void EndMatch(int localScore, int remoteScore) { MatchRoomState state = m_state; if (state == MatchRoomState.MyTurn || state == MatchRoomState.RemoteTurn) { string key = PlatformManager.MyID.ToString(); string key2 = m_remotePlayer.ID.ToString(); Dictionary dictionary = new Dictionary(); if (localScore > remoteScore) { dictionary[key] = 1; dictionary[key2] = 2; } else if (localScore < remoteScore) { dictionary[key] = 2; dictionary[key2] = 1; } else { dictionary[key] = 1; dictionary[key2] = 1; } Matchmaking.ReportResultsInsecure(m_matchRoom, dictionary).OnComplete(GenericErrorCheckCallback); } TransitionToState(MatchRoomState.None); } private void OnApplicationQuit() { Matchmaking.Cancel(); if (m_matchRoom != 0) { Rooms.Leave(m_matchRoom); } } private void TransitionToState(MatchRoomState state) { MatchRoomState state2 = m_state; m_state = state; switch (m_state) { case MatchRoomState.None: m_matchButtonText.text = "Find Match"; m_remotePlayer = null; Matchmaking.Cancel(); if (m_matchRoom != 0) { Rooms.Leave(m_matchRoom); m_matchRoom = 0uL; } break; case MatchRoomState.Queued: m_matchButtonText.text = "Leave Queue"; Matchmaking.Enqueue2("VR_BOARD_GAME_POOL").OnComplete(MatchmakingEnqueueCallback); break; case MatchRoomState.Configuring: m_matchButtonText.text = "Cancel Match"; break; case MatchRoomState.MyTurn: case MatchRoomState.RemoteTurn: m_matchButtonText.text = "Cancel Match"; break; } } private void MatchmakingEnqueueCallback(Message untyped_msg) { if (untyped_msg.IsError) { Debug.Log(untyped_msg.GetError().Message); TransitionToState(MatchRoomState.None); return; } Message message = (Message)untyped_msg; MatchmakingEnqueueResult data = message.Data; m_infoText.text = string.Format("Avg Wait Time: {0}s\nMax Expected Wait: {1}s\nIn Last Hour: {2}\nRecent Percentage: {3}%", data.AverageWait, data.MaxExpectedWait, data.MatchesInLastHourCount, data.RecentMatchPercentage); } private void MatchFoundCallback(Message msg) { if (msg.IsError) { Debug.Log(msg.GetError().Message); TransitionToState(MatchRoomState.None); } else if (m_state == MatchRoomState.Queued) { Matchmaking.JoinRoom(msg.Data.ID, true).OnComplete(MatchmakingJoinRoomCallback); m_matchRoom = msg.Data.ID; } } private void MatchmakingJoinRoomCallback(Message msg) { if (msg.IsError) { Debug.Log(msg.GetError().Message); TransitionToState(MatchRoomState.None); } else if (m_state == MatchRoomState.Queued) { int num = ((msg.Data.UsersOptional != null) ? msg.Data.UsersOptional.Count : 0); Debug.Log("Match room joined: " + m_matchRoom + " count: " + num); TransitionToState(MatchRoomState.Configuring); if (msg.Data.UsersOptional != null && msg.Data.UsersOptional.Count == 2) { ProcessRoomData(msg.Data); } } } private void MatchmakingRoomUpdateCallback(Message msg) { if (msg.IsError) { Debug.Log(msg.GetError().Message); TransitionToState(MatchRoomState.None); return; } string text = ((msg.Data.OwnerOptional == null) ? string.Empty : msg.Data.OwnerOptional.OculusID); int num = ((msg.Data.UsersOptional != null) ? msg.Data.UsersOptional.Count : 0); Debug.LogFormat("Room Update {0}\n Owner {1}\n User Count {2}\n Datastore Count {3}\n", msg.Data.ID, text, num, msg.Data.DataStore.Count); if (msg.Data.ID != m_matchRoom) { Debug.Log("Unexpected room update from: " + msg.Data.ID); } else { ProcessRoomData(msg.Data); } } private void ProcessRoomData(Oculus.Platform.Models.Room room) { m_lastUpdateTime = Time.time; if (m_state == MatchRoomState.Configuring) { if (room.UsersOptional != null) { foreach (User item in room.UsersOptional) { if (PlatformManager.MyID != item.ID) { Debug.Log("Found remote user: " + item.OculusID); m_remotePlayer = item; break; } } } if (m_remotePlayer == null) { return; } bool flag = DoesLocalUserGoFirst(); TransitionToState((!flag) ? MatchRoomState.RemoteTurn : MatchRoomState.MyTurn); Matchmaking.StartMatch(m_matchRoom).OnComplete(GenericErrorCheckCallback); m_gameController.StartOnlineMatch(m_remotePlayer.OculusID, flag); } if (m_state == MatchRoomState.RemoteTurn && room.DataStore.ContainsKey(m_remotePlayer.OculusID) && room.DataStore[m_remotePlayer.OculusID] != string.Empty) { ProcessRemoteMove(room.DataStore[m_remotePlayer.OculusID]); TransitionToState(MatchRoomState.MyTurn); } if (m_state == MatchRoomState.MyTurn && room.OwnerOptional != null && room.OwnerOptional.ID == PlatformManager.MyID) { m_gameController.MarkRemoteTurnComplete(); } if (room.UsersOptional == null || (room.UsersOptional != null && room.UsersOptional.Count != 2)) { Debug.Log("Other user quit the room"); m_gameController.RemoteMatchEnded(); } } private void ProcessRemoteMove(string moveString) { Debug.Log("Processing remote move string: " + moveString); string[] array = moveString.Split(':'); GamePiece.Piece piece = (GamePiece.Piece)Enum.Parse(typeof(GamePiece.Piece), array[0]); int num = int.Parse(array[1]); int num2 = int.Parse(array[2]); num = 2 - num; num2 = 2 - num2; m_gameController.MakeRemoteMove(piece, num, num2); } public void SendLocalMove(GamePiece.Piece piece, int boardX, int boardY) { string text = string.Format("{0}:{1}:{2}", piece.ToString(), boardX, boardY); Debug.Log("Sending move: " + text); Dictionary dictionary = new Dictionary(); dictionary[PlatformManager.MyOculusID] = text; dictionary[m_remotePlayer.OculusID] = string.Empty; Rooms.UpdateDataStore(m_matchRoom, dictionary).OnComplete(UpdateDataStoreCallback); TransitionToState(MatchRoomState.RemoteTurn); } private void UpdateDataStoreCallback(Message msg) { if (m_state == MatchRoomState.RemoteTurn) { Rooms.UpdateOwner(m_matchRoom, m_remotePlayer.ID); } } private bool DoesLocalUserGoFirst() { if (m_matchRoom % 2 == 0) { return PlatformManager.MyID < m_remotePlayer.ID; } return PlatformManager.MyID > m_remotePlayer.ID; } private void GenericErrorCheckCallback(Message msg) { if (msg.IsError) { Debug.Log(msg.GetError().Message); TransitionToState(MatchRoomState.None); } } } }