Files
2026-02-21 16:45:37 +08:00

297 lines
8.2 KiB
C#

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<string, int> dictionary = new Dictionary<string, int>();
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<MatchmakingEnqueueResult> message = (Message<MatchmakingEnqueueResult>)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<Oculus.Platform.Models.Room> 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<Oculus.Platform.Models.Room> 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<Oculus.Platform.Models.Room> 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<string, string> dictionary = new Dictionary<string, string>();
dictionary[PlatformManager.MyOculusID] = text;
dictionary[m_remotePlayer.OculusID] = string.Empty;
Rooms.UpdateDataStore(m_matchRoom, dictionary).OnComplete(UpdateDataStoreCallback);
TransitionToState(MatchRoomState.RemoteTurn);
}
private void UpdateDataStoreCallback(Message<Oculus.Platform.Models.Room> 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);
}
}
}
}