プログラム研究 備忘録

java,C#,Unity等の備忘録です。経済理論も少し。

ゲームサーバの起動方法② Scriptメモ

using UnityEngine;
using System.Collections;

public class NetworkManager : MonoBehaviour {
    // ゲームタイプ名.
    const string GameTypeName = "SampleDaze"; //
    
    // ローカルIPアドレスとポート.
    const string LocalServerIP = "127.0.0.1"; // 開発用.
    const int ServerPort = 25000;
    
    string playerName;
    string gameServerName;
    
    void Start()
    {
        playerName = "Player"+Random.Range(0,99999999).ToString();
        gameServerName = "Server"+Random.Range(0,99999999).ToString();
        UpdateHostList();
    }
    
    
    // 状態.
    public enum Status {
        NoError,                // エラーなし.
        
        LaunchingServer,        // サーバー起動中.
        ServerLaunched,            // サーバーが起動に成功.
        LaunchServerFailed,        // サーバーの起動に失敗.
        
        ConnectingToServer,        // サーバーに接続中.
        ConnectedToServer,        // サーバーに接続に成功.
        ConnectToServerFailed,    // サーバーへの接続に失敗.
        
        DisconnectedFromServer, // サーバーから切断された.
    };
    
    
    Status _status = Status.NoError;
    public Status status {get{return _status;} private set{_status = value;}}
    
    // サーバーを起動する.
    public void LaunchServer(string roomName)
    {
        status = Status.LaunchingServer;
        StartCoroutine(LaunchServerCoroutine(gameServerName));
    }
    
    bool useNat = false; // natパンチスルーを使用するか.
    IEnumerator CheckNat()
    {
        bool doneTesting = false; // 接続テストが終わったか.
        bool probingPublicIP = false;
        float timer = 0;
        useNat = false;
        
        // 接続テストをしてNATパンチスルーが必要かしらべる.
        while (!doneTesting) {
            ConnectionTesterStatus connectionTestResult = Network.TestConnection();
            switch (connectionTestResult) {
            case ConnectionTesterStatus.Error:
                // 問題が発生した.
                doneTesting = true;
                break;
                
            case ConnectionTesterStatus.Undetermined:
                // 調査中.
                doneTesting = false;
                break;
                
            case ConnectionTesterStatus.PublicIPIsConnectable:
                // パブリックIPアドレスを持っているのでNATパンチスルーは使わなくていい.
                useNat = false;
                doneTesting = true;
                break;
                
                
            case ConnectionTesterStatus.PublicIPPortBlocked:
                // パブリックIPアドレスを持っているようだがポートがブロックされていて接続できない.
                useNat = false;
                if (!probingPublicIP) {
                    connectionTestResult = Network.TestConnectionNAT();
                    probingPublicIP = true;
                    timer = Time.time + 10;
                }
                
                else if (Time.time > timer) {
                    probingPublicIP = false;         // reset
                    useNat = true;
                    doneTesting = true;
                }
                break;
            case ConnectionTesterStatus.PublicIPNoServerStarted:
                // パブリックIPアドレスを持っているがサーバーが起動していない.
                break;
                
            case ConnectionTesterStatus.LimitedNATPunchthroughPortRestricted:
            case ConnectionTesterStatus.LimitedNATPunchthroughSymmetric:
                // NATパンチスルーに制限がある.
                // サーバーに接続できないクライアントがあるかもしれない.
                useNat = true;
                doneTesting = true;
                break;
            case ConnectionTesterStatus.NATpunchthroughAddressRestrictedCone:
            case ConnectionTesterStatus.NATpunchthroughFullCone:
                // NATパンチスルーによりサーバーとクライアンは問題なく接続できる.
                useNat = true;
                doneTesting = true;
                break;
                
            default:
                Debug.Log ( "Error in test routine, got " + connectionTestResult);
                break;
            }
            yield return null;
        }
    }

    
    
    // サーバーを起動するコルーチン.
    IEnumerator LaunchServerCoroutine(string roomName)
    {
        yield return  StartCoroutine(CheckNat());
        
        // サーバーを起動する.
        NetworkConnectionError error = Network.InitializeServer(32,ServerPort,useNat);
        if (error !=  NetworkConnectionError.NoError) {
            Debug.Log("Can't Launch Server");
            status = Status.LaunchServerFailed;
        } else {
            // マスターサーバーにゲームサーバーを登録する.
            MasterServer.RegisterHost(GameTypeName, gameServerName);
        }
        
    }
    
    // サーバーに接続する.
    public void ConnectToServer(string serverGuid,bool connectLocalServer)
    {
        status = Status.ConnectingToServer;
        if (connectLocalServer)
            Network.Connect(LocalServerIP,ServerPort);
        else
            Network.Connect(serverGuid);
    }
    
    
    // サーバーが起動した.
    void OnServerInitialized()
    {
        status = Status.ServerLaunched;
    }
    
    // サーバーに接続した.
    void OnConnectedToServer()
    {
        status = Status.ConnectedToServer;
    }
    
    // サーバーへの接続に失敗した.
    void OnFailedToConnect(NetworkConnectionError error) {
        Debug.Log("FailedToConnect: " + error.ToString());
        status = Status.ConnectToServerFailed;
    }
    
    // プレイヤーが切断した.
    // (サーバーが動作しているコンピュータで呼び出される).
    void OnPlayerDisconnected(NetworkPlayer player) {
        Network.RemoveRPCs(player);
        Network.DestroyPlayerObjects(player);
    }
    
    // サーバーから切断された.
    void OnDisconnectedFromServer(NetworkDisconnection info) {
        Debug.Log("DisconnectedFromServer: " + info.ToString());
        status = Status.DisconnectedFromServer;
        Application.LoadLevel(0);
    }    
    
    // ステータスを得る.
    public Status GetStatus()
    {
        return status;
    }

    // プレイヤーネームを得る.
    public string GetPlayerName()
    {
        return playerName;
    }


    void OnDestroy()
    {
        if (Network.isServer) {
            MasterServer.UnregisterHost ();
            Network.Disconnect ();
        }
    }

    //-------------------- ロビー関連. --------------------
    // マスターサーバに登録されているゲームサーバのリストを更新する.
    public void UpdateHostList()
    {
        MasterServer.ClearHostList();
        MasterServer.RequestHostList(GameTypeName);
    }
    
    // スターサーバに登録されているゲームサーバのリストを取得する.
    public HostData GetHostList()
    {
        return MasterServer.PollHostList();
    }
    
    // マスターサーバとNATファシリテータのIPアドレスを設定する.
    void SetMasterServerAndNatFacilitatorIP(string masterServerAddress,string facilitatorAddress)
    {
        MasterServer.ipAddress = masterServerAddress;
        Network.natFacilitatorIP = facilitatorAddress;
    }
    
    // マスターサーバーへの登録を削除する.
    public void UnregisterHost()
    {
        MasterServer.UnregisterHost();
    }
    
    //-------------------- 設定GUI -------------------
    void OnGUI()
    {
        if ((Network.isServer || Network.isClient))
            return;
        
        // 高さ480の(0,0)中心を基準にする.
        float scale = Screen.height / 480.0f;
        GUI.matrix = Matrix4x4.TRS(new Vector3(Screen.width * 0.5f,Screen.height * 0.5f,0),Quaternion.identity,new Vector3(scale,scale,1.0f));
        
        GUI.Window(0, new Rect(-200,-200,400,400), NetworkSettingWindow, "Network Setting");
    }
    
    Vector2 scrollPosition;
    
    void NetworkSettingWindow(int windowID) {
        // プレイヤー名の設定.
        GUILayout.BeginHorizontal();
        GUILayout.Label("Player Name: ");
        playerName = GUILayout.TextField(playerName,32);
        GUILayout.EndHorizontal();
        
        // ゲームサーバー名の設定.
        GUILayout.BeginHorizontal();
        GUILayout.Label("Game Server Name: ");
        gameServerName = GUILayout.TextField(gameServerName,32);
        GUILayout.EndHorizontal();
        
        // ゲームサーバーを起動する.
        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        if (GUILayout.Button ("Launch"))
            LaunchServer(gameServerName);
        GUILayout.EndHorizontal();
        GUILayout.Space(20);
        
        // ゲームサーバーリスト.
        GUILayout.BeginHorizontal();
        GUILayout.Label("Game Server List (Click To Connect):");
        GUILayout.FlexibleSpace();
        if (GUILayout.Button("Refresh"))
            UpdateHostList();
        GUILayout.EndHorizontal();
        
        scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.Width(380), GUILayout.Height(200));
        HostData
hosts = GetHostList();  // サーバ一覧を取得.
        if (hosts.Length > 0) {
            foreach (HostData host in hosts)
                if (GUILayout.Button(host.gameName,GUI.skin.box,GUILayout.Width(360)))
                    ConnectToServer(host.guid,false);
        } else
            GUILayout.Label("No Server");
        GUILayout.EndScrollView();
        
        // ローカルサーバに接続.
        if (GUILayout.Button("Connect Local Server")) {
            ConnectToServer("",true);
        }
        
        // ステータスの表示.
        GUILayout.Label("Status: "+status.ToString());
        
    }
}