Created
August 23, 2016 09:48
-
-
Save arun02139/c1113703b3dbe98cb0be668870a27442 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEngine.UI; | |
using UnityEngine.SceneManagement; | |
using UnityEngine.Networking; | |
using UnityEngine.Networking.Types; | |
using UnityEngine.Networking.Match; | |
using System.Collections; | |
namespace Prototype.NetworkLobby | |
{ | |
public class LobbyManager : NetworkLobbyManager | |
{ | |
static short MsgKicked = MsgType.Highest + 1; | |
static public LobbyManager s_Singleton; | |
[Header("Unity UI Lobby")] | |
[Tooltip("Time in second between all players ready & match start")] | |
public float prematchCountdown = 5.0f; | |
[Space] | |
[Header("UI Reference")] | |
public LobbyTopPanel topPanel; | |
public RectTransform mainMenuPanel; | |
public RectTransform lobbyPanel; | |
public LobbyInfoPanel infoPanel; | |
public LobbyCountdownPanel countdownPanel; | |
public GameObject addPlayerButton; | |
protected RectTransform currentPanel; | |
public Button backButton; | |
public Text statusInfo; | |
public Text hostInfo; | |
//Client numPlayers from NetworkManager is always 0, so we count (throught connect/destroy in LobbyPlayer) the number | |
//of players, so that even client know how many player there is. | |
[HideInInspector] | |
public int _playerNumber = 0; | |
//used to disconnect a client properly when exiting the matchmaker | |
[HideInInspector] | |
public bool _isMatchmaking = false; | |
protected bool _disconnectServer = false; | |
protected ulong _currentMatchID; | |
protected LobbyHook _lobbyHook; | |
void Start() | |
{ | |
s_Singleton = this; | |
_lobbyHook = GetComponent<Prototype.NetworkLobby.LobbyHook>(); | |
currentPanel = mainMenuPanel; | |
backButton.gameObject.SetActive(false); | |
// GetComponent<Canvas>().enabled = true; | |
DontDestroyOnLoad(gameObject); | |
SetServerInfo("Offline", "None"); | |
} | |
public override void OnLobbyClientSceneChanged(NetworkConnection conn) | |
{ | |
Debug.Log (string.Format ("LobbyManager.OnLobbyClientSceneChanged: SceneManager.GetSceneAt(0).name={0} (SceneManager.sceneCount={1})", | |
SceneManager.GetSceneAt(0).name, SceneManager.sceneCount)); | |
if (SceneManager.GetSceneAt(0).name == lobbyScene) | |
{ | |
if (topPanel.isInGame) | |
{ | |
ChangeTo(lobbyPanel); | |
if (_isMatchmaking) | |
{ | |
if (conn.playerControllers[0].unetView.isServer) | |
{ | |
backDelegate = StopHostClbk; | |
} | |
else | |
{ | |
backDelegate = StopClientClbk; | |
} | |
} | |
else | |
{ | |
if (conn.playerControllers[0].unetView.isClient) | |
{ | |
backDelegate = StopHostClbk; | |
} | |
else | |
{ | |
backDelegate = StopClientClbk; | |
} | |
} | |
} | |
else | |
{ | |
ChangeTo(mainMenuPanel); | |
} | |
topPanel.ToggleVisibility(true); | |
topPanel.isInGame = false; | |
} | |
else | |
{ | |
ChangeTo(null); | |
Destroy(GameObject.Find("MainMenuUI(Clone)")); | |
//backDelegate = StopGameClbk; | |
topPanel.isInGame = true; | |
topPanel.ToggleVisibility(false); | |
} | |
} | |
public void ChangeTo(RectTransform newPanel) | |
{ | |
if (currentPanel != null) | |
{ | |
currentPanel.gameObject.SetActive(false); | |
} | |
if (newPanel != null) | |
{ | |
newPanel.gameObject.SetActive(true); | |
} | |
currentPanel = newPanel; | |
if (currentPanel != mainMenuPanel) | |
{ | |
backButton.gameObject.SetActive(true); | |
} | |
else | |
{ | |
backButton.gameObject.SetActive(false); | |
SetServerInfo("Offline", "None"); | |
_isMatchmaking = false; | |
} | |
} | |
public void DisplayIsConnecting() | |
{ | |
var _this = this; | |
infoPanel.Display("Connecting...", "Cancel", () => { _this.backDelegate(); }); | |
} | |
public void SetServerInfo(string status, string host) | |
{ | |
statusInfo.text = status; | |
hostInfo.text = host; | |
} | |
public delegate void BackButtonDelegate(); | |
public BackButtonDelegate backDelegate; | |
public void GoBackButton() | |
{ | |
backDelegate(); | |
} | |
// ----------------- Server management | |
public void AddLocalPlayer() | |
{ | |
TryToAddPlayer(); | |
} | |
public void RemovePlayer(LobbyPlayer player) | |
{ | |
player.RemovePlayer(); | |
} | |
public void SimpleBackClbk() | |
{ | |
ChangeTo(mainMenuPanel); | |
} | |
public void StopHostClbk() | |
{ | |
if (_isMatchmaking) | |
{ | |
matchMaker.DestroyMatch((NetworkID)_currentMatchID, 0, OnDestroyMatch); // HARDCODE | |
_disconnectServer = true; | |
} | |
else | |
{ | |
StopHost(); | |
} | |
ChangeTo(mainMenuPanel); | |
} | |
public void StopClientClbk() | |
{ | |
StopClient(); | |
if (_isMatchmaking) | |
{ | |
StopMatchMaker(); | |
} | |
ChangeTo(mainMenuPanel); | |
} | |
public void StopServerClbk() | |
{ | |
StopServer(); | |
ChangeTo(mainMenuPanel); | |
} | |
class KickMsg : MessageBase { } | |
public void KickPlayer(NetworkConnection conn) | |
{ | |
conn.Send(MsgKicked, new KickMsg()); | |
} | |
public void KickedMessageHandler(NetworkMessage netMsg) | |
{ | |
infoPanel.Display("Kicked by Server", "Close", null); | |
netMsg.conn.Disconnect(); | |
} | |
//=================== | |
public override void OnStartServer () | |
{ | |
base.OnStartServer (); // empty stub as of Unity 5.4 (gets called near start of function NetworkManager.StartServer) | |
} | |
public override void OnStartHost() | |
{ | |
base.OnStartHost(); | |
ChangeTo(lobbyPanel); | |
backDelegate = StopHostClbk; | |
SetServerInfo("Hosting", networkAddress); | |
} | |
public override void OnMatchCreate (bool success, string extendedInfo, MatchInfo matchInfo) | |
{ | |
base.OnMatchCreate (success, extendedInfo, matchInfo); | |
_currentMatchID = (ulong)matchInfo.networkId; | |
} | |
public override void OnDestroyMatch (bool success, string extendedInfo) | |
{ | |
base.OnDestroyMatch (success, extendedInfo); | |
if (_disconnectServer) | |
{ | |
StopMatchMaker(); | |
StopHost(); | |
} | |
} | |
//allow to handle the (+) button to add/remove player | |
public void OnPlayersNumberModified(int count) | |
{ | |
_playerNumber += count; | |
int localPlayerCount = 0; | |
foreach (PlayerController p in ClientScene.localPlayers) | |
localPlayerCount += (p == null || p.playerControllerId == -1) ? 0 : 1; | |
addPlayerButton.SetActive(localPlayerCount < maxPlayersPerConnection && _playerNumber < maxPlayers); | |
} | |
// ----------------- Server callbacks ------------------ | |
//we want to disable the button JOIN if we don't have enough player | |
//But OnLobbyClientConnect isn't called on hosting player. So we override the lobbyPlayer creation | |
public override GameObject OnLobbyServerCreateLobbyPlayer(NetworkConnection conn, short playerControllerId) | |
{ | |
GameObject obj = Instantiate(lobbyPlayerPrefab.gameObject) as GameObject; | |
LobbyPlayer newPlayer = obj.GetComponent<LobbyPlayer>(); | |
newPlayer.ToggleJoinButton(numPlayers + 1 >= minPlayers); | |
for (int i = 0; i < lobbySlots.Length; ++i) | |
{ | |
LobbyPlayer p = lobbySlots[i] as LobbyPlayer; | |
if (p != null) | |
{ | |
p.RpcUpdateRemoveButton(); | |
p.ToggleJoinButton(numPlayers + 1 >= minPlayers); | |
} | |
} | |
return obj; | |
} | |
public override void OnLobbyServerPlayerRemoved(NetworkConnection conn, short playerControllerId) | |
{ | |
for (int i = 0; i < lobbySlots.Length; ++i) | |
{ | |
LobbyPlayer p = lobbySlots[i] as LobbyPlayer; | |
if (p != null) | |
{ | |
p.RpcUpdateRemoveButton(); | |
p.ToggleJoinButton(numPlayers + 1 >= minPlayers); | |
} | |
} | |
} | |
public override void OnLobbyServerDisconnect(NetworkConnection conn) | |
{ | |
for (int i = 0; i < lobbySlots.Length; ++i) | |
{ | |
LobbyPlayer p = lobbySlots[i] as LobbyPlayer; | |
if (p != null) | |
{ | |
p.RpcUpdateRemoveButton(); | |
p.ToggleJoinButton(numPlayers >= minPlayers); | |
} | |
} | |
} | |
// NOTE: called towards the end of the NetworkLobbyManager.SceneLoadedForPlayer function. From the Unity | |
// docs: "This is called on the server when it is told that a client has finished switching from the | |
// lobby scene to a game player scene." NOTE: if we return 'false', the lobby player will not be replaced | |
// with the game player (i.e. NetworkLobbyManager.SceneLoadedForPlayer will return early before | |
// NetworkServer.ReplacePlayerForConnection is called) | |
public override bool OnLobbyServerSceneLoadedForPlayer(GameObject lobbyPlayer, GameObject gamePlayer) | |
{ | |
// sanity-check (this should never be the case since it's a server-side callback) | |
if (!NetworkServer.active) | |
{ | |
ClientDebugUI.i.Log (string.Format ("LobbyManager.OnLobbyServerSceneLoadedForPlayer: unexpected, returning false"), GameColors.Red); | |
return false; | |
} | |
// this hook allows you to apply state data from the lobby-player to the game-player | |
// just subclass "LobbyHook" and add it to the lobby object. | |
if (_lobbyHook) | |
{ | |
ServerDebugUI.i.Log (string.Format ("LobbyManager.OnLobbyServerSceneLoadedForPlayer: lobby hook found for player {0}", lobbyPlayer.name)); | |
// execute the lobby hook logic (presumably utilizing info from the lobby player to setup teh game player) | |
_lobbyHook.OnLobbyServerSceneLoadedForPlayer (this, lobbyPlayer, gamePlayer); | |
} | |
NetworkIdentity gamePlayerNetIdentity = gamePlayer.GetComponent<NetworkIdentity> (); | |
bool gamePlayerHasNetIdentity = gamePlayerNetIdentity != null; | |
string gamePlayerNetIdentityString = " gamePlayerNetIdentity: " + (gamePlayerHasNetIdentity ? gamePlayerNetIdentity.netId.ToString() : "(null)"); | |
NetworkIdentity lobbyPlayerNetIdentity = lobbyPlayer.GetComponent<NetworkIdentity> (); | |
bool lobbyPlayerHasNetIdentity = lobbyPlayerNetIdentity != null; | |
string lobbyPlayerNetIdentityString = " lobbyPlayerNetIdentity: " + (lobbyPlayerHasNetIdentity ? lobbyPlayerNetIdentity.netId.ToString() : "(null)"); | |
// create each player's units by spawning on the server | |
if (gamePlayerNetIdentity != null) | |
{ | |
ServerDebugUI.i.Log (string.Format ("LobbyManager.OnLobbyServerSceneLoadedForPlayer: ready to spawn player units!", "")); | |
ServerDebugUI.i.Log (gamePlayerNetIdentityString); | |
ServerDebugUI.i.Log (lobbyPlayerNetIdentityString); | |
SpawnPlayerUnits (gamePlayerNetIdentity); | |
} | |
// ..this shouldn't happen (gamePlayer should be NetworkPlayer prefab, which has a NetworkIdentity) | |
else | |
{ | |
ServerDebugUI.i.Log (string.Format ("LobbyManager.OnLobbyServerSceneLoadedForPlayer: no NetworkIdentity " + | |
"component found on gamePlayer {0}", gamePlayer.name), GameColors.Red); | |
} | |
return true; | |
} | |
// --- Countdown management | |
// AMM NOTE: only seems to be called on the host | |
public override void OnLobbyServerPlayersReady() | |
{ | |
bool allready = true; | |
for(int i = 0; i < lobbySlots.Length; ++i) | |
{ | |
if(lobbySlots[i] != null) | |
allready &= lobbySlots[i].readyToBegin; | |
} | |
Debug.Log(string.Format ("LobbyManager.OnLobbyServerPlayersReady: allready = {0} (NetworkServer.active = {1})", allready, NetworkServer.active)); | |
if(allready) | |
StartCoroutine(ServerCountdownCoroutine()); | |
} | |
public IEnumerator ServerCountdownCoroutine() | |
{ | |
float remainingTime = prematchCountdown; | |
int floorTime = Mathf.FloorToInt(remainingTime); | |
while (remainingTime > 0) | |
{ | |
yield return null; | |
remainingTime -= Time.deltaTime; | |
int newFloorTime = Mathf.FloorToInt(remainingTime); | |
if (newFloorTime != floorTime) | |
{//to avoid flooding the network of message, we only send a notice to client when the number of plain seconds change. | |
floorTime = newFloorTime; | |
for (int i = 0; i < lobbySlots.Length; ++i) | |
{ | |
if (lobbySlots[i] != null) | |
{//there is maxPlayer slots, so some could be == null, need to test it before accessing! | |
(lobbySlots[i] as LobbyPlayer).RpcUpdateCountdown(floorTime); | |
} | |
} | |
} | |
} | |
for (int i = 0; i < lobbySlots.Length; ++i) | |
{ | |
if (lobbySlots[i] != null) | |
{ | |
(lobbySlots[i] as LobbyPlayer).RpcUpdateCountdown(0); | |
} | |
} | |
ServerChangeScene(playScene); | |
} | |
// ----------------- Client callbacks ------------------ | |
public override void OnClientConnect(NetworkConnection conn) | |
{ | |
base.OnClientConnect(conn); | |
infoPanel.gameObject.SetActive(false); | |
conn.RegisterHandler(MsgKicked, KickedMessageHandler); | |
if (!NetworkServer.active) | |
{//only to do on pure client (not self hosting client) | |
ChangeTo(lobbyPanel); | |
backDelegate = StopClientClbk; | |
SetServerInfo("Client", networkAddress); | |
} | |
} | |
public override void OnClientDisconnect(NetworkConnection conn) | |
{ | |
Debug.Log (string.Format ("LobbyManager.OnClientDisconnect: conn = \n{0}", conn.PrettyPrint())); | |
base.OnClientDisconnect(conn); | |
ChangeTo(mainMenuPanel); | |
} | |
public override void OnClientError(NetworkConnection conn, int errorCode) | |
{ | |
ChangeTo(mainMenuPanel); | |
infoPanel.Display("Cient error : " + (errorCode == 6 ? "timeout" : errorCode.ToString()), "Close", null); | |
} | |
// create a single 'soldier' unit (index 0) | |
void SpawnPlayerUnits(NetworkIdentity netIdentity) | |
{ | |
// safety-check | |
if(this.spawnPrefabs.Count != 1) | |
{ | |
ServerDebugUI.i.Log (string.Format("LobbyManager.SpawnPlayerUnits: spawnPrefabs.Count={0} (NetworkServer.active={1}), aborting", | |
spawnPrefabs.Count, NetworkServer.active), GameColors.Red); | |
} | |
GameObject soldierUnitPrefab = spawnPrefabs [0]; | |
string prefabName = soldierUnitPrefab == null ? "(null)" : soldierUnitPrefab.name; | |
ServerDebugUI.i.Log (string.Format("LobbyManager.SpawnPlayerUnits: spawning {0} for gamePlayer ({1})", | |
prefabName, netIdentity.netId)); | |
// instantiate (on the server) | |
var unit = (GameObject)Instantiate(soldierUnitPrefab); | |
// spawn on clients across the network | |
NetworkServer.Spawn (unit); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment