PhotonServer服务器利用NHibernate操作数据库与客户端交互(登录、注册、多人位置同步)

本文介绍了如何结合NHibernate和MySQL数据库,利用 PhotonServer 实现服务器端的登录、注册功能,并进行玩家位置的同步。首先,详细说明了将NHibernate相关文件复制到服务器端工程的过程,包括修改命名空间和配置文件。接着,阐述了服务器与客户端的公共内容,如枚举类型定义,以及服务器端请求处理和事件发送的实现。最后,讨论了客户端的Unity工程设置,登录注册流程,以及游戏场景中角色位置的同步处理。
摘要由CSDN通过智能技术生成

1. 服务器端

1.1 服务器端工程准备

        此次项目内容是对上两次的整和,所以前两篇博文是单个功能的基础,分别是①NHibernate和MySQL交互,②PhotonServer的使用。这次项目也是在这两个基础之上进行的,很多直接拷贝过来进行修改;数据库还是用mygamedb,所以对PhotonServer目录下deploy\bin_Win64中PhotonControl.exe.config的配置文件不会更改,只用到了其中的Users表,Users表包含userID和username、password。

        NHibernate和MySQL交互工程如下:


        其中,

①hibernate.cfg.xml为NHibernate连接数据库的配置文件,名称不可更改,且属性为“始终复制到输出路径”;

②User.hbm.xml为数据库中Users表与定义的User类对应的配置文件,属性为“不复制,嵌入的资源”;

③User为定义的与Users表对应的字段;NHibernateHelper是对NHibernate创建会话的一个封装; ④IUserManager定义了操作Users表的方法(例如:对Users表添加、删除、修改、通过UserID查找、通过username查找、账号匹配等方法);

⑤而UserManager就是继承自IUserManager用NHibernate的会话实现这些方法。

        将所提到的类及配置文件(如有目录就包扩目录)全部复制到MyGameServer工程下,如图,本来的属性设置不变,会将程序集名和命名空间设置为MyGameServer的;!!!!!!!!重要:要将NHibernate和MySQL以及Log4Net所需引用进来的,Common是Common建后引用的。



下面介绍详细复制来文件的更改:

1.1.1 IUserManager.cs

        将命名空间修改为MyGameServer,应用所在的User类也改为using MyGameServer.Model。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MyGameServer.Model;

namespace MyGameServer.Manager
{
    interface IUserManager
    {
        void Add(User user);
        void Update(User user);
        void Remove(User user);
        User GetById(int id);
        User GetByUsername(string username);
        ICollection<User> GetAllUsers();

        bool VerifyUser(string username, string password);//验证用户名和密码
    }
}

1.1.2 UserManager.cs

        本来的引用命名空间变为MyGameServer.Model。

using System;
using System.Collections.Generic;
using MyGameServer.Manager;
using NHibernate;
using NHibernate.Criterion;
using MyGameServer.Model;

namespace MyGameServer.Manager
{
    class UserManager :IUserManager
    {
        public void Add(Model.User user)
        {
            /*第一种
            ISession session = NHibernateHelper.OpenSession();
            session.Save(user);
            session.Close();
            */
            using (ISession session = NHibernateHelper.OpenSession())
            {
                using (ITransaction transaction = session.BeginTransaction())
                {
                    session.Save(user);
                    transaction.Commit();
                }
            }
        }

        /// <summary>
        /// 得到表中所有内容
        /// </summary>
        /// <returns></returns>
        public ICollection<User> GetAllUsers()
        {
            using (ISession session = NHibernateHelper.OpenSession())
            {
                IList<User> users = session.CreateCriteria(typeof(User)).List<User>();
                return users;
            }
        }

        public User GetById(int id)
        {
            using (ISession session = NHibernateHelper.OpenSession())
            {
                //事务(事务中的一系列事件,只要有一个不成功,之前成功的也会回滚,即插入成功的又被删除,修改成功的又恢复.....)
                //    transaction = session.BeginTransaction();//开启事务
                using (ITransaction transaction = session.BeginTransaction())
                {
                    User user= session.Get<User>(id);
                    transaction.Commit();

                    return user;
                }
            }
        }

        public User GetByUsername(string username)
        {
            using (ISession session = NHibernateHelper.OpenSession())
            {
                /*
                ICriteria criteria= session.CreateCriteria(typeof(User));
                criteria.Add(Restrictions.Eq("Username", username));//添加一个查询条件,第一个参数表示对哪个属性(字段)做限制,第二个表示值为多少

                User user = criteria.UniqueResult<User>();
                */
                User user = session.CreateCriteria(typeof(User)).Add(Restrictions.Eq("Username", username)).UniqueResult<User>();
                return user;
                
            }
        }

        /// <summary>
        /// NHibernate删除时根据主键更新,所以传来的对象user中得有主键
        /// </summary>
        /// <param name="user"></param>
        public void Remove(User user)
        {
            using (ISession session = NHibernateHelper.OpenSession())
            {
                using (ITransaction transaction = session.BeginTransaction())
                {
                    session.Delete(user);
                    transaction.Commit();
                }
            }
        }

        /// <summary>
        /// NHibernate更新时根据主键更新,所以传来的对象user中得有主键
        /// </summary>
        /// <param name="user"></param>
        public void Update(User user)
        {
            using (ISession session = NHibernateHelper.OpenSession())
            {
                using (ITransaction transaction = session.BeginTransaction())
                {
                    session.Update(user);
                    transaction.Commit();
                }
            }
        }

        public bool VerifyUser(string username, string password)
        {
            using (ISession session = NHibernateHelper.OpenSession())
            {
                User user = session
                    .CreateCriteria(typeof(User))
                    .Add(Restrictions.Eq("Username", username))
                    .Add(Restrictions.Eq("Password", password))
                    .UniqueResult<User>();
                if (user == null) return false;
                return true;
            }
        }
    }
}

1.1.3 User.hmb.xml

        只需将程序集名和User类所在位置更改。

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="MyGameServer"  
                   namespace="MyGameServer.Model"> <!--assembly表示程序集,namespace所在文件夹Model-->

  <class name="User" table="users"><!--name为类名,table为表名-->
    <id name="ID" column="id" type="Int32"><!--id name对应为类中变量名,type为nhibernate的类型-->
    <generator class="native"></generator>
    </id><!--主键配置完成-->
    <property name="Username" column="username" type="String"></property>
    <property name="Password" column="password" type="String"></property>
    <property name="Registerdate" column="registerdate" type="Date"></property>
  </class>

</hibernate-mapping>

1.1.4 User.cs

        更改命名空间为MyGameServer。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGameServer.Model
{
    public class User
    {
        public virtual int ID { get; set; }
        public virtual string Username { get; set; }
        public virtual string Password { get; set; }
        public virtual DateTime Registerdate { get; set; }

    }
}

1.1.5 hibernate.cfg.xml

        连接数据库的配置文件不需要更改。

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
    <property name="dialect">NHibernate.Dialect.MySQL5Dialect</property><!--版本-->
    <property name="connection.driver_class">NHibernate.Driver.MySqlDataDriver</property><!--使用什么数据库-->
    <property name="connection.connection_string">Server=localhost;Database=mygamedb;User ID=root;Password=root;</property>
    <property name="show_sql">true</property>
  </session-factory>
</hibernate-configuration>

1.1.6 NHibernateHelper.cs

        也只需要更改命名空间。

using NHibernate;
using NHibernate.Cfg;

namespace MyGameServer
{
    class NHibernateHelper
    {
        private static ISessionFactory _sessionFactory;

        private static ISessionFactory SessionFactory
        {
            get
            {
                if(_sessionFactory==null)
                {
                    var configuration = new Configuration();
                    configuration.Configure();//解析hibernate.cfg.xml
                    configuration.AddAssembly("MyGameServer");//解析映射文件User.hbm.xml

                    _sessionFactory = configuration.BuildSessionFactory();
                }
                return _sessionFactory;
            }
        }

        public static ISession OpenSession()
        {
            return SessionFactory.OpenSession();//打开一个跟数据库的会话
        }
    }
}

1.2 服务器端和客户端公共所需

        服务器端和客户端都所需要的内容定义在此工程中,例如将客户端发送来的请求类型用枚举类型进行区分,将服务器发送的事件类型用枚举类型区分,将服务器发送给客户端的参数进行枚举类型区分,将返回给客户端的单个值用枚举类型区分等等。下面详细介绍。

1.2.1 工程创建

        因为要在客户端和服务器都需要用,所以将工程创建为类库,同服务器端工程一样,如下图,最后生成dll文件在服务器端和客户端(Unity)进行使用,因为unity工程所使用的dll文件.Net版本不能超过3.5,所以将Common工程属性的.NET版本设置为3.5。



最终

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王大匣

你的鼓励是我创作最大动力,谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值