Related Posts Plugin for WordPress, Blogger...

6-16 Finishing Sign Up Mechanism

前幾章將登入完成以後,接著來製作註冊功能吧。註冊功能與登入功能非常相似,相信大家要自行完成註冊功能沒什麼難度。首先,在Client端新增SignupRequest,繼承Request,實作OnDefaultRequest。

完成發送Request的部分後,回到Inspector畫面,Operation Code選擇為Signup。

接著到Server端新增SignupHandler繼承自BaseHandler,需要在建構子指定OperationCode為Signup。

在NoliahFantasyServer.cs主類中記得要在Dictionary中新增新的SignupHandler。如不懂為何要做這一步的話,請記得將前兩章都看一下唷。
6-15 Using Handler To Respond Requisition In Photon Server
https://3dactionrpg.blogspot.tw/2018/05/6-15-using-handler-to-respond.html

6-14 Using Dictionary To Manage All Request

 
接下來處理我們在SignupHandler中的OnOperationRequest部分吧。先從Parameters中取得帳號跟密碼。

再使用UserManager確認該用戶是否已存在,如不存在才建立新帳號,如已存在則建立失敗。並使用ReturnCode方式回傳註冊結果。

回到Client端的SignupRequest,接收來自Server的ReturnCode後,將剩下的處理交給SignupWindow類。
 主要因為註冊動作牽涉到UI變動,這部分的職責應劃分給SignupWindow。

以下提供本次有變動的原始碼。
Client端
SignupWindow.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class SignupWindow : Panel {

 [SerializeField] InputField accountInput;
 [SerializeField] InputField passwordInput;
 [SerializeField] LoginWindow loginWindow;
 [SerializeField] Text hintText;

 SignupRequest signupRequest;

 void Start(){
  base.Start ();
  signupRequest = GetComponent ();
 }

 public void OnSignupButton(){
  hintText.text = string.Empty;
  // 設定帳號及密碼參數後,呼叫OnDefaultRequest發送Request給Photon
  signupRequest.account = accountInput.text;
  signupRequest.password = passwordInput.text;
  signupRequest.OnDefaultRequest ();
 }

 public void OnShowLoginButton(){
  this.Hide ();
  loginWindow.Show ();
 }

 public void OnSignupResponse(ReturnCode returnCode){
  if (returnCode == ReturnCode.Success) {
   hintText.text = "註冊成功";
  } else {
   hintText.text = "該帳號已存在";
  }
 }
}


SignupRequest.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SignupRequest : Request {
 
 [HideInInspector] public string account;
 [HideInInspector] public string password;

 SignupWindow signupWindow;

 void Start(){
  base.Start ();
  signupWindow = GetComponent ();
 }

 public override void OnDefaultRequest ()
 {
  Dictionary data = new Dictionary ();
  data.Add((byte)ParameterCode.Acccount, account);
  data.Add((byte)ParameterCode.Password, password);
  // 向Server發出Request,true代表建立可靠連接
  PhotonEngine.Instance.GetPeer().OpCustom((byte)operationCode, data, true);
 }

 public override void OnOperationResponse (ExitGames.Client.Photon.OperationResponse operationResponse)
 {
  ReturnCode returnCode = (ReturnCode)operationResponse.ReturnCode;
  signupWindow.OnSignupResponse (returnCode);
 }

}


Server端
SignupHandler.cs:

using System;
using Photon.SocketServer;
using NoliahFantasyServer.Constant;
using NoliahFantasyServer.Manager;
using NoliahFantasyServer.Model;

namespace NoliahFantasyServer.Handler
{
    public class SignupHandler : BaseHandler
    {
        public SignupHandler()
        {
            operationCode = OperationCode.Signup;
        }

        public override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters, ClientPeer clientPeer)
        {
            // 從OperationRequest取得帳號密碼資訊
            object account;
            operationRequest.Parameters.TryGetValue((byte)ParameterCode.Acccount, out account);
            object password;
            operationRequest.Parameters.TryGetValue((byte)ParameterCode.Password, out password);

            // 從資料庫中查詢用戶是否已存在
            UserManager userManager = new UserManager();
            Users users = userManager.GetByAccount(account as string);

            // 使用short類型的ReturnCode簡單回傳結果
            OperationResponse operationResponse = new OperationResponse((byte)OperationCode.Signup);
            // 用戶不存在,建立帳號
            if(users == null){
                users = new Users() { 
                    Account = account as string,
                    Pwd = password as string,
                    Registerdate = DateTime.Now
                };
                userManager.Add(users);
                operationResponse.ReturnCode = (short)ReturnCode.Success;
            }else{
                // 用戶已存在,回傳訊息
                operationResponse.ReturnCode = (short)ReturnCode.Failed;
            }
            // 發送Response
            clientPeer.SendOperationResponse(operationResponse, sendParameters);
        }
    }
}


NoliahFantasyServer.cs:

using System;
using System.IO;
using System.Collections.Generic;
using Photon.SocketServer;
using ExitGames.Logging;
using ExitGames.Logging.Log4Net;
using log4net.Config;
using NHibernate;
using NHibernate.Cfg;
using NoliahFantasyServer.Constant;
using NoliahFantasyServer.Handler;
using NoliahFantasyServer.Model;
using NoliahFantasyServer.Manager;

namespace NoliahFantasyServer
{
    public class NoliahFantasyServer : ApplicationBase
    {

        public static readonly ILogger logger = LogManager.GetCurrentClassLogger();
        public static Dictionary handlerDict =
            new Dictionary();

        // 當Client端發出Request的時候
        protected override PeerBase CreatePeer(InitRequest initRequest)
        {
            return new MyClientPeer(initRequest);
        }

        // Server端啟動的時候初始化
        protected override void Setup()
        {
            InitLogger();
            InitHandler();
        }

        // Server端關閉的時候
        protected override void TearDown()
        {
        }

        void InitLogger()
        {
            // 日誌初始化
            log4net.GlobalContext.Properties["Photon:ApplicationLogPath"] = 
                Path.Combine(this.ApplicationRootPath, "bin_Win64", "log");
            FileInfo loggerConfig = new FileInfo(Path.Combine(this.BinaryPath, "log4net.config"));
            if (loggerConfig.Exists)
            {
                // 設置使用log4net的Log功能
                LogManager.SetLoggerFactory(ExitGames.Logging.Log4Net.Log4NetLoggerFactory.Instance);
                // 讓log4net讀取config
                XmlConfigurator.ConfigureAndWatch(loggerConfig);
            }
            logger.Info("Setup Log4Net Compeleted!");
        }

        void InitHandler(){
            LoginHandler loginHandler = new LoginHandler();
            handlerDict.Add(loginHandler.operationCode, loginHandler);
            SignupHandler signupHandler = new SignupHandler();
            handlerDict.Add(signupHandler.operationCode, signupHandler);
        }

    }
}


接下來測試看看吧,首先輸入一個不存在的帳號密碼。嘗試登入後出現帳號或密碼錯誤。

接著來進行註冊,註冊成功。

再次按下註冊鈕,確實有檢查,並顯示該帳號已存在。

回到登入畫面,嘗試登入後顯示登入成功啦!

查詢MySQL資料庫後也確認該帳號確實有加進資料庫,不過這邊還是先提醒大家一點,密碼的儲存最好使用SHA-256並加鹽之類的方式儲存,才具有安全性唷,可不能這麼大喇喇地存在資料庫裡。

留言