作用:简单的开始,以MyGameServer为例,最终目的生成类库.dll给server用
新建项目—Visual C#—类库—写个名字MyGameServer—创建
这是dll后缀文件,不可以自己启动的
解决方案资源管理器—MyGameServer项目—右键—生成
可以在MyGameServer-MyGameServer-bin-Debug里生成dll文件
项目MyGameServer—属性
看是否.NET4.5
Photon路径:
C:\Photon-OnPremise-Server-SDK_v4-0-29-11263\deploy
1、
deploy文件夹里新建文件夹MyGameServer
2、
MyGameServer文件夹里新建文件夹bin
bin不可改名字
项目MyGameServer—属性—生成—输出—输出路径
为上面的bin
ctrl + S 保存一下
解决方案资源管理器—MyGameServer项目—引用—右键—添加引用—浏览—浏览—目标C/D盘—Photon-OnPremise-Server-SDK_v4-0-29-11263—lib
引用5个:
ExitGamesLibs.dll—————————————Photon
Photon.StocketServer.dll——————————Photon
PhotonHostRuntimeInterfaces.dll——————-Photon
ExitGames.Logging.Log4Net.dll——————-日志的
log4net.dll————————————————-日志的
骚操作:解决方案资源管理器—MyGameServer项目—管理NuGet程序包里搜
找C:\Photon-OnPremise-Server-SDK_v4-0-29-11263\src-server\Mmo\Photon.MmoDemo.Server
里的log4net.config—复制ctrl+c
vs—解决方案资源管理器—点击一下MyGameServer项目—黏贴ctrl+v
让log4net.config与类在一个目录
点击一下log4net.config—属性—高级—复制到输出目录—始终复制
让信息复制到C:\Photon-OnPremise-Server-SDK_v4-0-29-11263\deploy\MyGameServer\bin
修改文件第5行
这个文档的百分号是错误的,不要复制
value="\\\\\\\\\\\\\\\\\\\\\\\\\\\%property{Photon:ApplicationLogPath}\\MyGame.Server.log" /> #######修改名字mmo-MyGame
可以删除Class1.cs
解决方案资源管理器—MyGameServer项目—Class1.cs
解决方案资源管理器—MyGameServer项目—右键—添加—新建项—类
名字一般与项目名称相同MyGameServer.cs—添加
以至于namespace与class都是MyGameServer
class MyGameServer前加上public,外界可以访问
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Photon.SocketServer;
using ExitGames.Logging;
using ExitGames.Logging.Log4Net;
using System.IO;
using log4net.Config;
namespace MyGameServer
{
//所有的server端都要继承ApplicationBase
public class MyGameServer : ApplicationBase
{
public static readonly ILogger log = LogManager.GetCurrentClassLogger();
//当一个peer客户端请求链接的时候创建peerbase
protected override PeerBase CreatePeer(InitRequest initRequest)
{
return new ClientPeer(initRequest);
}
//初始化
protected override void Setup()
{
//日志的初始化
log4net.GlobalContext.Properties["Photon:ApplicationLogPath"] = Path.Combine(this.ApplicationRootPath, "log");
FileInfo configFileInfo = new FileInfo(Path.Combine(this.BinaryPath,"log4net.config"));
if (configFileInfo.Exists)
{
LogManager.SetLoggerFactory(Log4NetLoggerFactory.Instance);//让Photon知道
XmlConfigurator.ConfigureAndWatch(configFileInfo);//让log4net这个插件读取配置文件
}
log.Info("初始化完成");
}
//server端关闭的时候
protected override void TearDown()
{
}
}
}
设置了日志
MyGame.Server.log————————程序自己配置的信息输出
C:\Photon-OnPremise-Server-SDK_v4-0-29-11263\deploy\log\MyGame.Server.log
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Photon.SocketServer;
using ExitGames.Logging;
using ExitGames.Logging.Log4Net;
using System.IO;
using log4net.Config;
using MyGameServer.Manager;
using Common;
using MyGameServer.Handler;
using MyGameServer.Threads;
namespace MyGameServer
{
//所有的server端 主类都要集成自applicationbase
public class MyGameServer:ApplicationBase
{
//日志C:\Users\chu\Desktop\Mygame\MyGameServer\MyGameServer.cs
public static readonly ILogger log = LogManager.GetCurrentClassLogger();
public static MyGameServer Instance//单例模式检测进来的code是什么
{
get;//外面只可以获取到
private set;里面可以修改
}
public Dictionary<OperationCode, BaseHandler> HandlerDict = new Dictionary<OperationCode, BaseHandler>();
public List<ClientPeer> peerList = new List<ClientPeer>();//通过这个集合可以访问到所有客户端的peer,从而向任何一个客户端发送数据
private SyncPositionThread syncPositionThread = new SyncPositionThread();//实例化线程
//当一个客户端请求链接的
//我们使用peerbase,表示和一个客户端的链接
protected override PeerBase CreatePeer(InitRequest initRequest)
{
log.Info("一个客户端连接过来了。。。。");
ClientPeer peer = new ClientPeer(initRequest);
peerList.Add(peer);//保存在服务器
return peer;
}
//server端初始化的时候
protected override void Setup()
{
Instance = this;
// 日志的初始化
log4net.GlobalContext.Properties["Photon:ApplicationLogPath"] = Path.Combine(this.ApplicationRootPath, "log");
FileInfo configFileInfo = new FileInfo( Path.Combine( this.BinaryPath ,"log4net.config"));
if (configFileInfo.Exists)
{
LogManager.SetLoggerFactory(Log4NetLoggerFactory.Instance);//让photon知道
XmlConfigurator.ConfigureAndWatch(configFileInfo);//让log4net这个插件读取配置文件
}
log.Info("服务器开启了!");
InitHandler();//初始化-收信息
syncPositionThread.Run();//线程开启
}
public void InitHandler()
{
//登录
LoginHandler loginHandler = new LoginHandler();
HandlerDict.Add(loginHandler.OpCode, loginHandler);
//错误找不到时用一个默认的来处理
DefaultHandler defaultHandler = new DefaultHandler();
HandlerDict.Add(defaultHandler.OpCode, defaultHandler);
//注册
RegisterHandler registerHandler = new RegisterHandler();
HandlerDict.Add(registerHandler.OpCode, registerHandler);
//位置更新
SyncPositionHandler syncPositionHandler = new SyncPositionHandler();
HandlerDict.Add(syncPositionHandler.OpCode, syncPositionHandler);
//其他玩家的信息
SyncPlayerHandler syncPlayerHandler = new SyncPlayerHandler();
HandlerDict.Add(syncPlayerHandler.OpCode, syncPlayerHandler);
}
//server端关闭的时候
protected override void TearDown()
{
syncPositionThread.Stop();//线程结束
log.Info("服务器应用关闭了");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Photon.SocketServer;
using PhotonHostRuntimeInterfaces;
namespace MyGameServer
{
public class ClientPeer:Photon.SocketServer.ClientPeer
{
public ClientPeer(InitRequest initRequest) : base(initRequest)
{
}
//客户端断开连接
protected override void OnDisconnect(DisconnectReason reasonCode, string reasonDetail)
{
}
//客户端连接
protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
{
switch (operationRequest.OperationCode)//通过OperationCode区分请求
{
case 1:
MyGameServer.log.Info("收到客户端发送的一个请求");
//得到参数
Dictionary<byte, object> data = operationRequest.Parameters;
object intValue;
data.TryGetValue(1, out intValue);
object stringValue;
data.TryGetValue(2, out stringValue);
MyGameServer.log.Info("参数:"+ intValue.ToString()+ stringValue.ToString());
//加上参数回去
OperationResponse opResponse = new OperationResponse(1);
Dictionary<byte, object> data2 = new Dictionary<byte, object>();
data2.Add(1, 100);//加数据
data2.Add(2, "aaBB中文");//加数据
opResponse.SetParameters(data2);
SendOperationResponse(opResponse, sendParameters);//给客户端一个响应
break;
default:
break;
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Photon.SocketServer;
using Common.Tools;
using Common;
using MyGameServer.Handler;
//客户端
namespace MyGameServer
{
public class ClientPeer:Photon.SocketServer.ClientPeer
{
public float x, y, z;//位置信息
public string username;
public ClientPeer(InitRequest initRequest):base(initRequest)
{
}
//处理客户端断开链接的后续工作
protected override void OnDisconnect(PhotonHostRuntimeInterfaces.DisconnectReason reasonCode, string reasonDetail)
{
MyGameServer.Instance.peerList.Remove(this);
}
//处理客户端的请求
protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
{
//实例化(获得请求码)
BaseHandler handler = DictTool.GetValue<OperationCode, BaseHandler>(MyGameServer.Instance.HandlerDict, (OperationCode)operationRequest.OperationCode);//MyGameServer的字典和事情码组成字典
if (handler != null)
{
handler.OnOperationRequest(operationRequest, sendParameters, this);
}
else
{
BaseHandler defaultHandler = DictTool.GetValue<OperationCode, BaseHandler>(MyGameServer.Instance.HandlerDict, OperationCode.Default);
defaultHandler.OnOperationRequest(operationRequest, sendParameters, this);
}
}
}
}
C:\Photon-OnPremise-Server-SDK_v4-0-29-11263\deploy\bin_Win64\PhotonControl
1、有没有”初始化完成”
2、Server is running