Unity3d accesses the beauty of MySQL database through PhotonServer

Posted by atzi on Mon, 05 Aug 2019 05:10:35 +0200

Links to the original text: https://blog.csdn.net/qq_33747722/article/details/78324586

Source download address: Click Open Link

The previous article described mapping classes and database tables using NHibernate

This article will simply encapsulate NHibernate data for easy invocation in PhotonServer server.

using NHibernate;
using NHibernate.Cfg;
using MyGameServer.Domain;
using NHibernate.Criterion;
using System.Collections.Generic;
 
namespace MyGameServer.Helper
{
    public static class NHibernateHelper
    {
        private static ISessionFactory sessionFactory = null;
        private static ISession session = null;
        public static ISession GetSession
        {
            get
            {
                if (sessionFactory == null)
                {
                    Configuration cfg = new Configuration();
                    //Resolve the fixed path configuration file nhibernate.cfg.xml
                    cfg.Configure();
                    //Mapping target assembly parses mapping file Student.xml...
                    cfg.AddAssembly(typeof(Student).Assembly);
                    //Getting session objects
                    sessionFactory = cfg.BuildSessionFactory();
                }
 
                session = sessionFactory.OpenSession();
 
                return session;
            }
 
            private set { }
        }
 
        //add rows
        public static void AddData<T>(T t)
        {
            using (ISession session = GetSession)
            {
                using (ITransaction transaction=session.BeginTransaction())
                {
                    GetSession.Save(t);
                    transaction.Commit();
                }
            }
        }
 
        //Adding columns
        public static void RemoveData<T>(T t)
        {
            using (ISession session = GetSession)
            {
                using (ITransaction transaction = session.BeginTransaction())
                {
                    GetSession.Delete(t);
                    transaction.Commit();
                }
            }
        }
 
        //Obtaining objects by ID
        public static T GetDataById<T>(int id)
        {
            using (ISession session = GetSession)
            {
                using (ITransaction transaction = session.BeginTransaction())
                {
                    T t = session.Get<T>(id);
                    transaction.Commit();
                    return t;
                }
            }
        }
 
        /// <summary>
        /// Getting objects by name
        /// </summary>
        /// <typeparam name="T"> objects to be retrieved </typeparam>
        /// <param name="dataBaseName">Column name in database </param>
        /// <param name="targetName">Get the object's target name</param>
        /// <returns></returns>
        public static T GetDataByName<T>(string dataBaseName, string targetName)
        {
            using (ISession session = GetSession)
            {
                T t = session.CreateCriteria(typeof(T)).Add(Restrictions.Eq(dataBaseName, targetName)).UniqueResult<T>();
                return t;
            }
        }
 
        /// <summary>
        /// Get all the objects in the table
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static ICollection<T> GetAllUsers<T>()
        {
            using (ISession session = GetSession)
            {
                IList<T> ts = session.CreateCriteria(typeof(T)).List<T>();
                return ts;
            }
        }
 
 
        //Query for objects with the same id and name
        public static bool VerifyUser<T>(params object[] arg)
        {
            using (ISession session = GetSession)
            {
                T t = session
                    .CreateCriteria(typeof(T))
                    .Add(Restrictions.Eq(arg[0].ToString(), arg[1]))//Class attribute name attribute value
                    .Add(Restrictions.Eq(arg[2].ToString(), arg[3]))
                    .UniqueResult<T>();
                if (t == null)
                {
                    return false;
                }
 
                return true;
            }
        }
 
        /// <summary>
        /// Update data table
        /// </summary>
        /// <typeparam name="T">Objects mapped by datasheets </typeparam>
        /// <param name="t"></param>
        public static void UpdateData<T>(T t)
        {
            using (ISession session = GetSession)
            {
                using (ITransaction transaction=session.BeginTransaction())
                {
                    session.Update(t);
                    transaction.Commit();
                }
            }
        }
    }
}

Call in main function

using NHibernate;
using NHibernate.Cfg;
using LJL.Domain;
using LJL.Helper;
 
namespace LJL
{
    class Program
    {
        static void Main(string[] args)
        {
            Student sd = new Student { mID = 6, mName = "Xiao Zhang", mScore = 10 };
            NHibernateHelper.AddData(sd);
        }
    }
}

Run the program. Everything is OK. Open SQLyog and add a row of data to the student table.

Next, call it in PhotonServer to interact with MySQL database

Integrate classes and configuration files into class libraries as shown below (note that you need to modify assemblies and namespaces in the following classes and configuration files)

The next step is to communicate with PhotonServer in the Unity3d game client and access the local database.

Create UI on Unity3d client (here simply drag in input boxes and buttons)

Create the script as shown below

Our game has many requests (such as login, registration, etc.)

So they all inherit from BaseRequest

using ExitGames.Client.Photon;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public abstract class BaseRequest : MonoBehaviour
{
    [HideInInspector]
    //The operation type of the request
    public Collective.OperationMode operationMode = Collective.OperationMode.Default;
 
    public virtual void Start() { }
 
    public abstract void OnOperationRequest();
    public abstract void OnOperationResponse(OperationResponse operationResponse);

}

Here the blogger simply makes a login request

using ExitGames.Client.Photon;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
public class LoginRequest : BaseRequest
{
    //User name
    private InputField mInputName;
    //Password
    private InputField mInputPassword;
 
    public override void Start()
    {
        operationMode = Collective.OperationMode.LOGIN;
        GameContext.GetInstance.AddRequest(this);
 
        mInputName = GameObject.Find("IDInputField").GetComponent<InputField>();
        mInputPassword = GameObject.Find("NameInputField").GetComponent<InputField>();
        //Logon button click event
        GameObject.Find("LoginButton").GetComponent<Button>().onClick.AddListener(() => { OnOperationRequest(); });
    }
 
    public override void OnOperationRequest()
    {
        GameContext.GetInstance.peer.OpCustom(
                                                (byte)this.operationMode,
                                                new Dictionary<byte, object> { { (byte)Collective.ParameterMode.NAME, mInputName.text }, { (byte)Collective.ParameterMode.PASSWORD, mInputPassword.text } },
                                                true
                                              );
    }
 
    public override void OnOperationResponse(OperationResponse operationResponse)
    {        
        Collective.OperationResult resultCode = (Collective.OperationResult)operationResponse.ReturnCode;
        if (resultCode == Collective.OperationResult.SUCCESS)
        {
            //Successful login
            Debug.Log("User logged in successfully");
        }
        else if(resultCode == Collective.OperationResult.FAIL)
        {
            //Logon failure
            Debug.Log("Logon failure");
        }
    }
}

Finally, I attach the GameContext script of the previous blog post, where some updates have taken place.

using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using ExitGames.Client.Photon;
 
public class GameContext : MonoBehaviour,IPhotonPeerListener
{
    /// <summary>
    /// Storage Operations Types and Requests
    /// </summary>
    public Dictionary<Collective.OperationMode, BaseRequest> requestDic = new Dictionary<Collective.OperationMode, BaseRequest>();
 
    public PhotonPeer peer;
 
    private static GameContext _instance;
    public static GameContext GetInstance
    {
        get
        {
            if (_instance == null)
            {
                _instance = GameObject.Find("GameContext").GetComponent<GameContext>();
            }
 
            return _instance;
        }
    }
 
    public void DebugReturn(DebugLevel level, string message)
    {       
    }
 
    //Receiving events from the server
    public void OnEvent(EventData eventData)
    {
        switch (eventData.Code)
        {
            case 0:
                //Getting event data
                object value = eventData.Parameters.FirstOrDefault(q => q.Key == 1).Value;
 
                Debug.Log(value.ToString());
 
                break;
            default:
                break;
        }
    }
 
    //Receive response data (client sends request)
    public void OnOperationResponse(OperationResponse operationResponse)
    {
        BaseRequest request = requestDic.FirstOrDefault(q => q.Key == (Collective.OperationMode)operationResponse.OperationCode).Value;
        if (request != null)
        {
            request.OnOperationResponse(operationResponse);
        }
        else
        {
            //Failed to obtain response data
            Debug.LogError("Failed to obtain response data");
        }
    }
 
    //Connection status send change
    public void OnStatusChanged(StatusCode statusCode)
    {
        Debug.Log("Changes in data connection status:" + statusCode);
    }
 
    private void Start()
    {
        //Transport Protocol UDP, Receiving Server-side Responses through Listener
        peer = new PhotonPeer(this, ConnectionProtocol.Udp);
        //Connect to local server
        peer.Connect("127.0.0.1:5055", "MYGameServer");
    }
 
    private void Update()
    {
        //Keep data connection with server in real time
        peer.Service();                 
    }
 
    private void OnDestroy()
    {
        if (peer != null && peer.PeerState == PeerStateValue.Connected)
        {
            //Disconnect
            peer.Disconnect();
        }
    }
 
    public void AddRequest(BaseRequest request)
    {
        if (request != null)
        {
            requestDic.Add(request.operationMode, request);
        }
        else
        {
            Debug.LogError("Add empty data");
        }
    }
 
    public void RemoveRequest(BaseRequest request)
    {
        if (request != null && requestDic.ContainsValue(request))
        {
            requestDic.Remove(request.operationMode);
        }
        else
        {
            Debug.LogError("Removal failure");
        }
    }
}

Collective is a generated class library, which contains some enumeration types that are used together on both client and server sides (source code is packaged last for everyone to learn)

Similar logic needs to be handled on the server side

It also creates request classes to inherit various requests from BaseRequest

In the main class, request classes are added to the dictionary container. When listening for data requests, the corresponding request classes are found to operate on database data (add, delete, change, check).

And return the final data to the client (success, fail ure)

BaseRequest.cs
 

using Photon.SocketServer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace MyGameServer.Request
{
    public abstract class BaseRequest
    {
        public Collective.OperationMode operationMode = Collective.OperationMode.DEDAULF;
 
        public abstract void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters, ClientPeer peer);        
    }
}

LoginRequest.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MyGameServer.Request;
using Photon.SocketServer;
using MyGameServer.Helper;
using MyGameServer.Domain;
 
namespace MyGameServer.Request
{
    public class LoginRequest : BaseRequest
    {
        public LoginRequest()
        {
            operationMode = Collective.OperationMode.LOGIN;
        }
 
        public override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters, ClientPeer peer)
        {
            Dictionary<byte, object> parameterDic = operationRequest.Parameters;
 
           
 
            bool result = NHibernateHelper.VerifyUser<Student>(
                                                    //Class attribute name, attribute value
                                                    "mID", int.Parse(parameterDic.FirstOrDefault(q => q.Key == (byte)Collective.ParameterMode.NAME).Value.ToString()),
                                                    "mName", parameterDic.FirstOrDefault(q => q.Key == (byte)Collective.ParameterMode.PASSWORD).Value.ToString()
                                                );
 
            MyGameServer.LOG.Info(parameterDic.FirstOrDefault(q => q.Key == (byte)Collective.ParameterMode.NAME).Value.ToString());
            MyGameServer.LOG.Info(parameterDic.FirstOrDefault(q => q.Key == (byte)Collective.ParameterMode.PASSWORD).Value.ToString());
 
            OperationResponse response = new OperationResponse(operationRequest.OperationCode);
            response.ReturnCode = (short)Collective.OperationResult.FAIL;
            if (result)
            {
                response.ReturnCode = (short)Collective.OperationResult.SUCCESS;
                MyGameServer.LOG.Info("Verification success");
            }
            peer.SendOperationResponse(response, sendParameters);
        }
    }
}

Attached is MyGameServer.cs on the server side of the article, which is updated here (adding a dictionary container to store the request class)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Photon.SocketServer;
using System.IO;
using ExitGames.Logging;
using ExitGames.Logging.Log4Net;
using log4net.Config;
using MyGameServer.Domain;
using MyGameServer.Helper;
using MyGameServer.Request;
 
namespace MyGameServer
{
    //Server Framework Main Class Framework Entry
    public class MyGameServer : Photon.SocketServer.ApplicationBase
    {
        public static Dictionary<byte, object> requestDic = new Dictionary<byte, object>();
 
        //Singleton pattern
        public static ILogger LOG = LogManager.GetCurrentClassLogger();    
 
        //Called when there is client access
        protected override PeerBase CreatePeer(InitRequest initRequest)
        {
            LOG.Info("There is a client connected to the server");
 
            AddRequestOperation();
 
            return new ClientPeer(initRequest);
        }
 
        //Called when the framework starts
        protected override void Setup()
        {
            //Setting profile properties
            log4net.GlobalContext.Properties["Photon:ApplicationLogPath"] = Path.Combine(Path.Combine(this.ApplicationRootPath, "bin_Win64"), "log");//Setting up the log file storage directory
 
            //Log Profile
            FileInfo logConfigFileInfo = new FileInfo(Path.Combine(this.BinaryPath, "log4net.config"));
            if (logConfigFileInfo.Exists)//Configuration file exists
            {
                //Set the Photon Log Plug-in to Log4Next
                LogManager.SetLoggerFactory(Log4NetLoggerFactory.Instance);
                //Log4Next plug-in reads configuration files
                XmlConfigurator.ConfigureAndWatch(logConfigFileInfo);
            }
 
            LOG.Info("Server initialization completed");            
        }
 
 
        //Add all the interactive requests contained to the dictionary
        private void AddRequestOperation()
        {
            requestDic.Clear();
 
            BaseRequest request = new LoginRequest();
            requestDic.Add((byte)request.operationMode, request);
        }
 
        //Called when the framework stops
        protected override void TearDown()
        {
            
        }
    }
}


The client class ClientPeer.cs data listening function needs to be modified.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Photon.SocketServer;
using PhotonHostRuntimeInterfaces;
using MyGameServer.Request;
 
namespace MyGameServer
{
    public class ClientPeer : Photon.SocketServer.ClientPeer
    {
        public ClientPeer(InitRequest ir) : base(ir) { }
 
        //The client disconnects
        protected override void OnDisconnect(DisconnectReason reasonCode, string reasonDetail)
        {
            
        }
 
        //The client requests operation
        protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {
            BaseRequest request = (BaseRequest)MyGameServer.requestDic.FirstOrDefault(q => q.Key == (byte)operationRequest.OperationCode).Value;
            if (request != null)
            {
                request.OnOperationRequest(operationRequest, sendParameters, this);
            }
            else
            {
                MyGameServer.LOG.Info("Failure to obtain request operation");
            }
        }   
    }
}

Regenerate the solution and open MyGameServer with PhotonControl

Open a client in Unity

Verify the data and find that everything is normal!!!

 

Topics: Session Database Attribute xml