mirror of
https://github.com/Leahnaya/TheKingsRace.git
synced 2026-09-14 21:35:17 -05:00
Rewrote Networking and Base Lobby Created
- Rewrote networking based on tutorials from MLAPI Demo Project and Dapper Dino - Created Lobby UI based on the turorial from Dapper Dino - Linked Existing UI into using the new networking - Modified Lobby Settings to only allow 3 players - Added Field for players to enter their player name
This commit is contained in:
8
Assets/Scripts/UI/Lobby.meta
Normal file
8
Assets/Scripts/UI/Lobby.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bac1def4c30048140986167189190078
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
31
Assets/Scripts/UI/Lobby/LobbyPlayerCard.cs
Normal file
31
Assets/Scripts/UI/Lobby/LobbyPlayerCard.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class LobbyPlayerCard : MonoBehaviour {
|
||||
|
||||
[Header("Panels")]
|
||||
[SerializeField] private GameObject waitingForPlayerPanel;
|
||||
[SerializeField] private GameObject playerDataPanel;
|
||||
|
||||
[Header("Data Display")]
|
||||
[SerializeField] private TMP_Text playerDisplayNameText;
|
||||
[SerializeField] private Image selectedCharacterImage;
|
||||
[SerializeField] private Toggle isReadyToggle;
|
||||
|
||||
public void UpdateDisplay(LobbyPlayerState lobbyPlayerState)
|
||||
{
|
||||
playerDisplayNameText.text = lobbyPlayerState.PlayerName;
|
||||
isReadyToggle.isOn = lobbyPlayerState.IsReady;
|
||||
|
||||
waitingForPlayerPanel.SetActive(false);
|
||||
playerDataPanel.SetActive(true);
|
||||
}
|
||||
|
||||
public void DisableDisplay()
|
||||
{
|
||||
waitingForPlayerPanel.SetActive(true);
|
||||
playerDataPanel.SetActive(false);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/UI/Lobby/LobbyPlayerCard.cs.meta
Normal file
11
Assets/Scripts/UI/Lobby/LobbyPlayerCard.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 311c1a64d12df464ab0b856d2aa3e5ae
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
21
Assets/Scripts/UI/Lobby/LobbyPlayerState.cs
Normal file
21
Assets/Scripts/UI/Lobby/LobbyPlayerState.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using MLAPI.Serialization;
|
||||
|
||||
public struct LobbyPlayerState : INetworkSerializable {
|
||||
public ulong ClientId;
|
||||
public string PlayerName;
|
||||
public bool IsReady;
|
||||
|
||||
public LobbyPlayerState(ulong clientId, string playerName, bool isReady)
|
||||
{
|
||||
ClientId = clientId;
|
||||
PlayerName = playerName;
|
||||
IsReady = isReady;
|
||||
}
|
||||
|
||||
public void NetworkSerialize(NetworkSerializer serializer)
|
||||
{
|
||||
serializer.Serialize(ref ClientId);
|
||||
serializer.Serialize(ref PlayerName);
|
||||
serializer.Serialize(ref IsReady);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/UI/Lobby/LobbyPlayerState.cs.meta
Normal file
11
Assets/Scripts/UI/Lobby/LobbyPlayerState.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 81e16a8360aa6c94094061211aef3e66
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
155
Assets/Scripts/UI/Lobby/LobbyUI.cs
Normal file
155
Assets/Scripts/UI/Lobby/LobbyUI.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
using System;
|
||||
using MLAPI;
|
||||
using MLAPI.Connection;
|
||||
using MLAPI.Messaging;
|
||||
using MLAPI.NetworkVariable.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class LobbyUI : NetworkBehaviour {
|
||||
|
||||
[Header("References")]
|
||||
[SerializeField] private LobbyPlayerCard[] lobbyPlayerCards;
|
||||
[SerializeField] private Button startGameButton;
|
||||
|
||||
private NetworkList<LobbyPlayerState> lobbyPlayers = new NetworkList<LobbyPlayerState>();
|
||||
|
||||
public override void NetworkStart()
|
||||
{
|
||||
if (IsClient)
|
||||
{
|
||||
lobbyPlayers.OnListChanged += HandleLobbyPlayersStateChanged;
|
||||
}
|
||||
|
||||
if (IsServer)
|
||||
{
|
||||
startGameButton.gameObject.SetActive(true);
|
||||
|
||||
NetworkManager.Singleton.OnClientConnectedCallback += HandleClientConnected;
|
||||
NetworkManager.Singleton.OnClientDisconnectCallback += HandleClientDisconnect;
|
||||
|
||||
foreach (NetworkClient client in NetworkManager.Singleton.ConnectedClientsList)
|
||||
{
|
||||
HandleClientConnected(client.ClientId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
lobbyPlayers.OnListChanged -= HandleLobbyPlayersStateChanged;
|
||||
|
||||
if (NetworkManager.Singleton)
|
||||
{
|
||||
NetworkManager.Singleton.OnClientConnectedCallback -= HandleClientConnected;
|
||||
NetworkManager.Singleton.OnClientDisconnectCallback -= HandleClientDisconnect;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsEveryoneReady()
|
||||
{
|
||||
// Make sure there is 3 players in the lobby
|
||||
if (lobbyPlayers.Count != 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Need to add a check to make sure that 2 are runners and 1 is king
|
||||
|
||||
foreach (var player in lobbyPlayers)
|
||||
{
|
||||
if (!player.IsReady)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void HandleClientConnected(ulong clientId)
|
||||
{
|
||||
var playerData = ServerGameNetPortal.Instance.GetPlayerData(clientId);
|
||||
|
||||
if (!playerData.HasValue) { return; }
|
||||
|
||||
lobbyPlayers.Add(new LobbyPlayerState(
|
||||
clientId,
|
||||
playerData.Value.PlayerName,
|
||||
false
|
||||
));
|
||||
}
|
||||
|
||||
private void HandleClientDisconnect(ulong clientId)
|
||||
{
|
||||
for (int i = 0; i < lobbyPlayers.Count; i++)
|
||||
{
|
||||
if (lobbyPlayers[i].ClientId == clientId)
|
||||
{
|
||||
lobbyPlayers.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
private void ToggleReadyServerRpc(ServerRpcParams serverRpcParams = default)
|
||||
{
|
||||
for (int i = 0; i < lobbyPlayers.Count; i++)
|
||||
{
|
||||
if (lobbyPlayers[i].ClientId == serverRpcParams.Receive.SenderClientId)
|
||||
{
|
||||
lobbyPlayers[i] = new LobbyPlayerState(
|
||||
lobbyPlayers[i].ClientId,
|
||||
lobbyPlayers[i].PlayerName,
|
||||
!lobbyPlayers[i].IsReady
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
private void StartGameServerRpc(ServerRpcParams serverRpcParams = default)
|
||||
{
|
||||
if (serverRpcParams.Receive.SenderClientId != NetworkManager.Singleton.LocalClientId) { return; }
|
||||
|
||||
if (!IsEveryoneReady()) { return; }
|
||||
|
||||
ServerGameNetPortal.Instance.StartGame();
|
||||
}
|
||||
|
||||
public void OnLeaveClicked()
|
||||
{
|
||||
GameNetPortal.Instance.RequestDisconnect();
|
||||
}
|
||||
|
||||
public void OnReadyClicked()
|
||||
{
|
||||
ToggleReadyServerRpc();
|
||||
}
|
||||
|
||||
public void OnStartGameClicked()
|
||||
{
|
||||
StartGameServerRpc();
|
||||
}
|
||||
|
||||
private void HandleLobbyPlayersStateChanged(NetworkListEvent<LobbyPlayerState> lobbyState)
|
||||
{
|
||||
for (int i = 0; i < lobbyPlayerCards.Length; i++)
|
||||
{
|
||||
if (lobbyPlayers.Count > i)
|
||||
{
|
||||
lobbyPlayerCards[i].UpdateDisplay(lobbyPlayers[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
lobbyPlayerCards[i].DisableDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
if(IsHost)
|
||||
{
|
||||
startGameButton.interactable = IsEveryoneReady();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/UI/Lobby/LobbyUI.cs.meta
Normal file
11
Assets/Scripts/UI/Lobby/LobbyUI.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea8a020e40c2c2443810c67a957f44e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/UI/Title.meta
Normal file
8
Assets/Scripts/UI/Title.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 791d1f5615272234d89da9396541ce1d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
106
Assets/Scripts/UI/Title/ConnectButtons.cs
Normal file
106
Assets/Scripts/UI/Title/ConnectButtons.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using MLAPI;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class ConnectButtons : MonoBehaviour {
|
||||
|
||||
// The IP Used to connect to the dedicated server
|
||||
const string DEDICATED_SERVER_IP = "127.0.0.1";
|
||||
const int DEDICATED_SERVER_PORT = 7777;
|
||||
|
||||
public GameObject ErrorPanel;
|
||||
public Text ErrorText;
|
||||
|
||||
public InputField ipAddressField;
|
||||
public TMP_InputField playerNameField;
|
||||
|
||||
private int connectionTimeoutTime = 5;
|
||||
|
||||
void Start() {
|
||||
// Make sure the Error Panel is not enabled to start
|
||||
ErrorPanel.SetActive(false);
|
||||
|
||||
PlayerPrefs.GetString("PlayerName");
|
||||
}
|
||||
|
||||
// Connect to the dedicated server
|
||||
public void ConnectDedicatedServer () {
|
||||
// Throw an error for now
|
||||
ThrowError("Not implemented yet.");
|
||||
}
|
||||
|
||||
// Host a private server
|
||||
public void HostPrivateServer() {
|
||||
// Set the players name
|
||||
PlayerPrefs.SetString("PlayerName", playerNameField.text);
|
||||
|
||||
// Start a server and join (hosting)
|
||||
GameNetPortal.Instance.StartHost();
|
||||
}
|
||||
|
||||
// Connect to a private server via IP Address
|
||||
public void ConnectToPrivateServer() {
|
||||
string ipAddress = ipAddressField.text;
|
||||
int port = 7777;
|
||||
|
||||
// Check if the IP Address is valid
|
||||
if (!ValidateIPv4(ipAddress)) {
|
||||
ThrowError("Invalid IP Address! Please enter a valid IP Address and try again!");
|
||||
return;
|
||||
}
|
||||
|
||||
// IP Address is valid - Attempt to connect
|
||||
|
||||
// Set the players name
|
||||
PlayerPrefs.SetString("PlayerName", playerNameField.text);
|
||||
|
||||
// Start the game client
|
||||
ClientGameNetPortal.Instance.StartClient(ipAddress, port);
|
||||
|
||||
// Run a coroutine to check if the client connects to the server
|
||||
StartCoroutine(checkIsConnectedClient());
|
||||
}
|
||||
|
||||
IEnumerator checkIsConnectedClient() {
|
||||
yield return new WaitForSecondsRealtime(connectionTimeoutTime);
|
||||
|
||||
if (!NetworkManager.Singleton.IsConnectedClient) {
|
||||
// Failed to connect to the server
|
||||
NetworkManager.Singleton.StopClient();
|
||||
|
||||
ThrowError("Could not connect to server!\nReason: Connection Timed Out");
|
||||
}
|
||||
}
|
||||
|
||||
private void ThrowError(string errorMsg) {
|
||||
ErrorText.text = errorMsg;
|
||||
|
||||
ErrorPanel.SetActive(true);
|
||||
}
|
||||
|
||||
public void DismissError() {
|
||||
ErrorText.text = "";
|
||||
|
||||
ErrorPanel.SetActive(false);
|
||||
}
|
||||
|
||||
// Method by: Habib (Stack Overflow)
|
||||
// https://stackoverflow.com/questions/11412956/what-is-the-best-way-of-validating-an-ip-address
|
||||
private bool ValidateIPv4(string ipString) {
|
||||
if (string.IsNullOrWhiteSpace(ipString)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string[] splitValues = ipString.Split('.');
|
||||
if (splitValues.Length != 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte tempForParsing;
|
||||
|
||||
return splitValues.All(r => byte.TryParse(r, out tempForParsing));
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/UI/Title/ConnectButtons.cs.meta
Normal file
11
Assets/Scripts/UI/Title/ConnectButtons.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7ea00cd263782d4484caf5ad9694247
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user