using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Threading;
public class UnityMPWifiNetMgr : BaseNetMgr
{
public DominosNetPlayer netPlayerPrefab;
private NetworkView cachedNetView;
private UdpClient udpServer;
private UdpClient udpClient;
private IPEndPoint udpReceiveEndPoint;
private string udpServerPort = "40400";
private int unityServerPort = 40401;
private string ip = "0.0.0.0";
private string ipBroadcast = "255.255.255.255";
private bool connected = false;
private string serverName = "";
private Thread clientThread;
private Thread serverThread;
public bool IsHost {
get {
return (GameManager.instance.State.ClientType == ClientType.Host );
}
}
public NetworkView CachedNetView {
get {
if (cachedNetView == null)
cachedNetView = GetComponent<NetworkView> ();
return this.cachedNetView;
}
set {
cachedNetView = value;
}
}
public void Awake ()
{
Application.runInBackground = true;
}
public override void Start ()
{
base.Start ();
StartCoroutine(BootMPGame());
}
public void OnDestroy ()
{
}
public override void OnDoPlayerConnect (object sender, BasePlayer player)
{
// notify local delegates
base.OnDoPlayerConnect (sender, player);
// if we are Host, then RPC call OnDoPlayerConnect's equivalent method
if (IsHost)
{
CachedNetView.RPC ("OnDoPlayerConnectRPC", RPCMode.OthersBuffered, player.Nic, player.NetPlayer);
}
}
[RPC]
public void OnDoPlayerConnectRPC (string nic, NetworkPlayer netPlayer, NetworkMessageInfo netInfo)
{
Debug.Log ("RPC call rec'd: " + netInfo);
// create NetPlayer, assign nic and NetPlayer reference, then add to Players
DominosNetPlayer newPlayer = Instantiate (
netPlayerPrefab,
GameManager.instance.otherPlayerSpawnPoint.position,
Quaternion.identity
) as DominosNetPlayer;
newPlayer.Nic = nic;
newPlayer.NetPlayer = netPlayer;
GameManager.instance.Players.Add (newPlayer);
// notify local delegates
base.OnDoPlayerConnect (this, newPlayer);
}
public override void OnDoPlayerDisconnect (object sender, BasePlayer player)
{
// notify local delegates
base.OnDoPlayerDisconnect (sender, player);
// if we are Host, then RPC call OnDoPlayerConnect's equivalent method
if (IsHost)
{
CachedNetView.RPC ("OnDoPlayerConnectRPC", RPCMode.OthersBuffered, player.Nic, player.NetPlayer);
}
}
// these delegate messages may have come from local senders, or via RPC call
public override void OnDoGameState (object sender, GameState newState)
{
// notify local delegates.
base.OnDoGameState (sender, newState);
// notify remote delegates via RPC, if we are host
if (GameManager.instance.State.ClientType != ClientType.Host)
return;
}
public override void OnDoPlayerTurnState (object sender, BasePlayer player, PlayerTurnStates newState)
{
// notify local delegates.
base.OnDoPlayerTurnState (sender, player, newState);
// notify remote delegates via RPC, if we are host
if (GameManager.instance.State.ClientType != ClientType.Host)
return;
}
public override void OnPlayBone (object sender, BasePlayer player, Bone playBone, Bone parentBone, BonePosition pos)
{
// notify local delegates.
base.OnPlayBone (sender, player, playBone, parentBone, pos);
if (GameManager.instance.State.ClientType != ClientType.Host)
return;
// notify remote delegates via RPC, if we are host
}
private IEnumerator BootMPGame ()
{
GameManager.instance.State.ClientType = ClientType.Unknown;
#if UNITY_IPHONE || UNITY_ANDROID
if (iPhoneSettings.internetReachability == iPhoneNetworkReachability.NotReachable)
{
Debug.LogWarning ("Internet not reachable");
yield return new WaitForSeconds (1);
}
#endif
// the udp client will start a thread, listen on port, for broadcast of server name
// then the ServerName property will be set
LoadUDPClient ();
yield return new WaitForSeconds (1);
if (serverName != string.Empty)
{
Debug.LogWarning ("client located server @ " + serverName);
Debug.LogWarning("client connecting....");
Network.Connect (serverName, unityServerPort);
}
else
{
Debug.LogWarning ("no udp server detected");
// force udpClient and thread to exit first
connected = true;
connected = false;
udpClient.Close ();
yield return 0;
Debug.LogWarning("udp client stopped");
// become the server
LoadUDPServer ();
}
if(GameManager.instance.State.ClientType == ClientType.Host)
{
//add DevicePlayer as Player 0
GameManager.instance.Players.Clear();
DevicePlayer.instance.NetPlayer = Network.player;
GameManager.instance.Players.Add( DevicePlayer.instance );
while( GameManager.instance.Players.Count < GameManager.instance.State.MaxPlayers )
{
Debug.LogWarning("waiting for players");
yield return new WaitForSeconds(1);
}
}
}
void OnFailedToConnect (NetworkConnectionError error)
{
Debug.LogWarning ("Could not connect to server: " + error);
}
void OnFailedToConnectToMasterServer (NetworkConnectionError info)
{
Debug.LogWarning ("Could not connect to master server: " + info);
}
void OnDisconnectedFromServer (NetworkDisconnection info)
{
if (Network.isServer)
Debug.LogWarning ("Local server connection disconnected");
else if (info == NetworkDisconnection.LostConnection)
Debug.LogWarning ("Lost connection to the server");
else
Debug.LogWarning ("Successfully diconnected from the server");
}
public void OnServerInitialized ()
{
Debug.LogWarning ("Unity Network Server initialized");
connected = true;
GameManager.instance.State.ClientType = ClientType.Host;
try
{
ip = Network.player.ipAddress.ToString ();
udpServer = new UdpClient (System.Convert.ToInt32 (udpServerPort));
udpReceiveEndPoint = new IPEndPoint (IPAddress.Parse (ip), System.Convert.ToInt32 (udpServerPort));
serverThread = new Thread (new ThreadStart (UDPServerTask));
serverThread.Start ();
}
catch {}
Debug.LogWarning ("UDP broadcasting of server ip: " + ip);
}
public void OnConnectedToServer ()
{
Debug.LogWarning ("Connected to server");
connected = true;
GameManager.instance.State.ClientType = ClientType.RemoteClient;
}
void OnPlayerConnected (NetworkPlayer player)
{
Debug.LogWarning ("Player connected from " + player.ipAddress + ":" + player.port);
}
void OnPlayerDisconnected (NetworkPlayer player)
{
Debug.LogWarning ("Server destroying player");
Network.RemoveRPCs (player, 0);
Network.DestroyPlayerObjects (player);
}
/// <summary>
/// creates receive point and client, starts the udpclient thread
/// </summary>
private void LoadUDPClient ()
{
Debug.LogWarning ("Starting UDP client...");
try
{
udpClient = new UdpClient (System.Convert.ToInt32 (udpServerPort));
udpReceiveEndPoint = new IPEndPoint (IPAddress.Parse (ip), System.Convert.ToInt32 (udpServerPort));
clientThread = new Thread (new ThreadStart (UDPClientTask));
clientThread.Start ();
Debug.LogWarning ("UDP client started");
}
catch
{}
}
/// <summary>
/// Reads the server name from any udp broadcasts.
/// </summary>
private void UDPClientTask ()
{
try {
while (true)
{
byte[] recData = udpClient.Receive (ref udpReceiveEndPoint);
System.Text.ASCIIEncoding encode = new System.Text.ASCIIEncoding ();
serverName = encode.GetString (recData);
if (serverName != string.Empty)
{
// if the server was selected above, and unity network connected, then close
// the udp client and break out of thread
if (connected)
{
udpClient.Close ();
break;
}
}
}
} catch {}
}
/// <summary>
/// Inits the Unity Server, and starts a thread to broadcast over udp.
/// </summary>
private void LoadUDPServer ()
{
Debug.LogWarning("Becoming Server...");
Network.InitializeSecurity ();
Network.InitializeServer (GameManager.instance.State.MaxPlayers, unityServerPort, false);
}
/// <summary>
/// broadcasts our ip address over udp. it will be read as ServerName property by the client.
/// </summary>
private void UDPServerTask ()
{
try {
while (true)
{
System.Text.ASCIIEncoding encode = new System.Text.ASCIIEncoding ();
byte[] sendData = encode.GetBytes (ip);
udpServer.Send (sendData, sendData.Length, ipBroadcast, System.Convert.ToInt32 (udpServerPort));
Thread.Sleep (100);
}
} catch {
}
}
}