using System.Collections.Generic; using Engine.Http; //using ThoughtWorks.QRCode.Codec; using System.Net.NetworkInformation; using UnityEngine; using System.IO; //using System.Drawing; using System.Text; //using System.Drawing.Imaging; using System; using LitJson; public delegate void HanlderNetException(int command, string msg); public delegate void HandlerNetDistributeQRCode(Texture2D texture); namespace Engine.Http { public class HttpPlayer { public string name; public int pid; public int machineID; public int score; public string wechat; public string avatarFile; public int rank; public Dictionary playerStages = new Dictionary(); public HttpPlayer() { } public void SetPlayerData(JsonData data) { name = data["name"].ToString(); wechat = data["wechat"].ToString(); avatarFile = data["avatar_file"].ToString(); score = System.Convert.ToInt32(data["score"].ToString()); pid = (int)data["pid"]; machineID = (int)data["machine_id"]; } public void SetRankData(JsonData data) { name = data["name"].ToString(); score = System.Convert.ToInt32(data["score"].ToString()); if(data["rank"] != null) { rank = (int)data["rank"]; } } public void AddStagePoint(int stageID, int star, int score, string stageTime) { PlayerStage stage; if(!playerStages.ContainsKey(stageID)) { stage = new PlayerStage(); playerStages.Add(stageID, stage); } else { stage = playerStages[stageID]; } stage.score = score; stage.star = star; stage.stageTime = stageTime; } } public class PlayerStage { public int star; public int score; public string stageTime; } /// /// 网络通信分发类 /// /// add by ch.ji /// /// public class HttpDistribute : System.Object { /// 二维码分辨率精度 public const int QR_CODE_SCALE = 1; #region 单例 /// 单利对象 private static HttpDistribute instance; /// 获得单利对象 public static HttpDistribute Instance { get { if (instance == null) { return instance = new HttpDistribute(); } return instance; } } #endregion #region 网络通讯基本参数配置 private string mGateWay = ""; private string mPort = ""; private string mHost = ""; private string mHostBMSGame = ""; private int mGameType = 0; private int mMachineID = 0; private int mCurrentPID = -1; private int mHID = -1; #endregion #region 私有属性 /// 是否开启轮询方式获取等待中的玩家 private bool IsPollingWaitingPlayers = true; /// 轮询获取等待中玩家的周期 private int mPWPTimeMax = 10 * 1000; /// 心跳检测连接的的时间周期 private int mNetTicTimeMax = 10 * 1000; /// 网络连接是否已断开 private bool isConnecting = false; /// http网络请求管理器引用 private HttpManager httpManager = HttpManager.GetInstance(); /// HTTP网络请求缓存 private Dictionary httpRequestCache = new Dictionary(); /// 等待中的玩家列表 private ObjectArray mWaitingPlayers = new ObjectArray(1000); /// 排行榜 private ObjectArray mRankPlayers = new ObjectArray(20); /// 当前正玩游戏的玩家(列表中第一位) private HttpPlayer mCurrentPlayer = new HttpPlayer(); /// 与服务端通信使用的物理地址 private string mMacAddress; #endregion #region 外部可设置的回调函数 /// 请求返回值异常回调函数 private HanlderNetException mOnNetExceptionHandler; /// 获取二维码的外部回调函数 private HandlerNetDistributeQRCode mOnQRCodeHandler; /// 轮询获取到等待中玩家的外部回调函数 private HandleHttpMessage mPollingWaitingPlayers; /// HTTP请求外部回调函数 private HandleHttpMessage mHttpMessage; #endregion /// /// 构造函数 /// public HttpDistribute() { } /// /// 初始化http网络请求分发器,入口 /// /// /// /// /// public void Init(string gateWay, int type, int port = -1) { mGateWay = gateWay; mPort = port.ToString(); mHost = (port == -1) ? mGateWay : mGateWay + mPort; mHostBMSGame = mHost + "/bms/game/"; mGameType = type; httpManager.AddHttpMessageEvent(OnNetDistributeSend); } #region 添加和删除外部回调函数 public void AddQRCodeHandler(HandlerNetDistributeQRCode handler) { mOnQRCodeHandler += handler; } public void RemoveQRCodeHandler(HandlerNetDistributeQRCode handler) { mOnQRCodeHandler -= handler; } public void AddWaitingPlayersHanlder(HandleHttpMessage handler) { mPollingWaitingPlayers += handler; } public void RemoveWaitingPlayersHanlder(HandleHttpMessage handler) { mPollingWaitingPlayers -= handler; } public void AddHttpMessageHandler(HandleHttpMessage handler) { mHttpMessage += handler; } public void RemoveHttpMessageHandler(HandleHttpMessage handler) { mHttpMessage -= handler; } public void AddNetExceptionHandler(HanlderNetException handler) { mOnNetExceptionHandler += handler; } public void RemoveNetExceptionHandler(HanlderNetException handler) { mOnNetExceptionHandler -= handler; } #endregion private string GetHostBMSGameURL(string serverMethodName) { StringBuilder url = new StringBuilder(mHostBMSGame); url.Append(serverMethodName); return url.ToString(); } private bool hasRequestCache(string url) { return httpRequestCache.ContainsKey(url); } /// /// 发送获取支付二维码的http请求 /// /// public void GetPayQRCodeHTTP() { string url = GetHostBMSGameURL(ServerMethod.SERVER_QRCODE); HttpRequest request = CreateRequest(url, (int)HTTPClientCommand.CMD_GET_QRCODE); Send(request); } #region 获取二维码 /// /// 获取支付二维码的回调函数 /// /// private void OnGetQRCode(HttpResponse result) { /*mMacAddress = result.ReadJsonData("mac").ToString(); string QRData = result.ReadJsonData("code").ToString(); QRCodeEncoder encoder = new QRCodeEncoder(); encoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;//编码方式(注意:BYTE能支持中文,ALPHA_NUMERIC扫描出来的都是数字) encoder.QRCodeScale = QR_CODE_SCALE;//大小(值越大生成的二维码图片像素越高) encoder.QRCodeVersion = 0;//版本(注意:设置为0主要是防止编码的字符串太长时发生错误) encoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.H;//错误效验、错误更正(有4个等级) Bitmap bmp = encoder.Encode(QRData, System.Text.Encoding.UTF8); Texture2D texture = CreateQRCodeTexture(bmp); if (mOnQRCodeHandler != null) mOnQRCodeHandler(texture); isConnecting = true; IsPollingWaitingPlayers = true;//开始轮询检测等待中的玩家 PollingWaitingPlayers(null);*/ } /// /// 创建支付二维码 /// /// /// /*private Texture2D CreateQRCodeTexture(Bitmap bmp) { Texture2D texture = new Texture2D(bmp.Width, bmp.Height, TextureFormat.RGBA32, false); UnityEngine.Color zeroColor = new UnityEngine.Color(0, 0, 0, 1f); for (int i = 0; i < bmp.Width; i++) { for (int j = 0; j < bmp.Height; j++) { System.Drawing.Color sysColor = bmp.GetPixel(i, j); int r = (int)sysColor.R; int g = (int)sysColor.G; int b = (int)sysColor.B; int a = (int)sysColor.A; if (r != 0 || g != 0 || b != 0 || a != 0) { float fr = (r != 0) ? r / 255f : 0f; float fg = (g != 0) ? g / 255f : 0f; float fb = (b != 0) ? b / 255f : 0f; float fa = (a != 0) ? a / 255f : 0f; UnityEngine.Color color = new UnityEngine.Color(fr, fg, fb, fa); texture.SetPixel(i, j, color); } else { texture.SetPixel(i, j, zeroColor); } } } texture.Apply(); return texture; }*/ #endregion /// /// 发送获取等待中的玩家列表的http请求 /// /// public void GetWaitingPlayersHTTP() { GetWaitingPlayersHTTP((int)HTTPClientCommand.CMD_GET_WAITING_PLAYERS); } #region 获取等待中玩家,包括轮询 /// /// 轮询获取等待中玩家列表 /// /// private void GetWaitingPlayersHTTP(int command) { string url = GetHostBMSGameURL(ServerMethod.GET_PLAYER_LIST); HttpRequest request = null; if (!hasRequestCache(url)) { request = CreateRequest(url, command); httpRequestCache.Add(url, request); } else { request = httpRequestCache[url]; } if (command != request.Code) request.Code = command; Send(request); httpRequestCache[url].ResetRequestParamContent(); } /// /// 轮询中获取到等待的玩家列表时的处理 /// /// private void OnGetWaitingPlayers(HttpResponse result) { IsPollingWaitingPlayers = false; JsonData data = result.ReadJsonData(); if (data.IsArray) { HttpPlayer target = null; JsonData player = null; mWaitingPlayers.SetEmpty(); for (int i = 0; i < data.Count; i++) { if (i >= mWaitingPlayers.Length) break; player = data[i]; target = new HttpPlayer(); target.SetPlayerData(player); mWaitingPlayers.Add(target); } target = mWaitingPlayers.Get(0); //target.AddStagePoint(player)//TODO 增加关卡数据的保存逻辑 IsPollingWaitingPlayers = (target == null); if (IsPollingWaitingPlayers) { mCurrentPID = -1; mMachineID = -1; TimerManager.Instance.WaitCallBack(mPWPTimeMax, PollingWaitingPlayers); } else { mCurrentPID = target.pid; mMachineID = target.machineID; TimerManager.Instance.WaitCallBack(mNetTicTimeMax, CheckNetStatuTic); } } if (mPollingWaitingPlayers != null) { mPollingWaitingPlayers(result); } } private void PollingWaitingPlayers(object param) { if (isConnecting && IsPollingWaitingPlayers) { GetWaitingPlayersHTTP((int)HTTPClientCommand.CMD_POLLING_WAITING_PLAYERS); } } #endregion /// /// 发送开始游戏的http请求 /// public void StartGameHTTP() { if (mCurrentPID == -1) return; string url = GetHostBMSGameURL(ServerMethod.SERVER_START_GAME); HttpRequest request = CreateRequest(url, (int)HTTPClientCommand.CMD_START_GAME); request.AddParam("pid", mCurrentPID.ToString()); request.AddParam("machine_id", mMachineID.ToString()); Send(request); } /// /// 游戏结束,发送游戏结果的http请求 /// public void CommitGameHTTP(int stageID, int score, int machineID = -1, int pID = -1, int hId = -1) { if (hId == -1) hId = mHID; if (machineID == -1) machineID = mMachineID; if (pID == -1) pID = mCurrentPID; if (pID == -1 || machineID == -1 || hId == -1) { CDebug.Log("Http Distribute: hid、pid、machine_id 可能不正确,游戏数据提交失败!"); return; } StringBuilder content = new StringBuilder(); JsonWriter writer = new JsonWriter(content); writer.WriteObjectStart(); writer.WritePropertyName("game_type");//必备参数 writer.Write(mGameType.ToString()); writer.WritePropertyName("machine_id");//必备参数 writer.Write(machineID.ToString()); writer.WritePropertyName("pid");//用户id writer.Write(pID.ToString()); writer.WritePropertyName("stage_id");//关卡id writer.Write(stageID.ToString()); writer.WritePropertyName("score");//关卡分数 writer.Write(score.ToString()); writer.WritePropertyName("hid");//区分游玩关卡的次数id writer.Write(hId.ToString()); writer.WriteObjectEnd(); string jsonParams = content.ToString(); string url = GetHostBMSGameURL(ServerMethod.SERVER_COMMIT_GAME); HttpRequest request = CreateRequest(url, (int)HTTPClientCommand.CMD_COMMIT_GAME, HttpMethod.POST); request.SetJSONParamContent(jsonParams); Send(request, false); } /// /// 获取玩家排行榜 /// /// public void GetRankHTTP(int pID = -1) { if(pID == -1) pID = mCurrentPID; if (pID == -1) return; string url = GetHostBMSGameURL(ServerMethod.SERVER_GET_RANK); HttpRequest request = CreateRequest(url, (int)HTTPClientCommand.CMD_GET_RANK); request.AddParam("pid", pID.ToString()); Send(request); } /// /// 发送HTTP网络请求 /// /// /// public void Send(HttpRequest request, bool applyBaseParams = true) { if (applyBaseParams) { request.AddParam("mac", MacAddress);//添加基本通信参数 request.AddParam("game_type", GameTypeParam); } httpManager.SendMessage(request);//发送网络请求 } #region 网络连接心跳检测 private void CheckNetStatuTic(object param) { if (isConnecting && !IsPollingWaitingPlayers) { CheckNetStatuHTTP(); } } private void CheckNetStatuHTTP() { string url = mHostBMSGame; HttpRequest request = null; if (!hasRequestCache(url)) { request = CreateRequest(url, (int)HTTPClientCommand.CMD_CHECK_NETSTATU); httpRequestCache.Add(url, request); }else { request = httpRequestCache[url]; } Send(request); httpRequestCache[url].ResetRequestParamContent(); } private void OnCheckNetStatu(HttpResponse responder) { if (!responder.isSuccess) { isConnecting = false; //TODO 提示网络已断开 }else { if(!IsPollingWaitingPlayers) { TimerManager.Instance.WaitCallBack(mNetTicTimeMax, CheckNetStatuTic); } } } #endregion /// /// 处理排行榜返回值 /// /// private void OnGetRank(HttpResponse result) { JsonData list = result.ReadJsonData("top_list");//{"name":"", "avatar_file":"", "pid":"", "wechat":""} JsonData playerData = result.ReadJsonData("player_data");//{"name":"", "avatar_file":"", "pid":"", "wechat":"", "rank":""} mCurrentPlayer.SetRankData(playerData); mRankPlayers.SetEmpty(); if (list.IsArray) { JsonData target = null; HttpPlayer player = null; for (int i = 0; i < list.Count; i++) { if (i >= mRankPlayers.Length) break; target = list[i]; player = new HttpPlayer(); player.SetRankData(target); mRankPlayers.Add(player); } CDebug.Log ("排行榜信息拿到"); //MessageCenter.Instance.Broadcast(GameEnum.MSG_GET_RANK_INFO_CALLBACK); } } #region 每帧检测的内容 public void OnUpdate(int nTime) { if (httpManager != null) httpManager.OnUpdate(nTime); } public void OnFixedUpdate(int nTime) { if (httpManager != null) httpManager.OnFixedUpdate(nTime); } #endregion #region 统一发送、响应请求 private HttpRequest CreateRequest(string url, int command, string method = HttpMethod.GET) { HttpRequest result = HttpRequest.OnCreateRequest();//构建网络请求对象 result.URL = url; result.Code = command; result.httpMethod = method; //request.requestTimeout = OnNetDistributeRequestTimeOut;//请求超时的回调函数 return result; } /// /// 统一处理网络请求返回值 /// /// /// private bool OnNetDistributeSend(HttpResponse result) { bool isSuccess = false; if (result != null && result.isSuccess) { isSuccess = true; int command = result.Code; switch (result.Code) { case (int)HTTPClientCommand.CMD_GET_QRCODE: OnGetQRCode(result); break; case (int)HTTPClientCommand.CMD_START_GAME: mHID = (int)result.ReadJsonData("hid"); break; case (int)HTTPClientCommand.CMD_POLLING_WAITING_PLAYERS: OnGetWaitingPlayers(result); break; case (int)HTTPClientCommand.CMD_CHECK_NETSTATU: OnCheckNetStatu(result); break; case (int)HTTPClientCommand.CMD_GET_RANK: OnGetRank(result); break; case (int)HTTPClientCommand.CMD_COMMIT_GAME: GetWaitingPlayersHTTP((int)HTTPClientCommand.CMD_POLLING_WAITING_PLAYERS);//提交完分数后再获取一次玩家的等待列表 return true; default: break; } if (mHttpMessage != null) mHttpMessage(result);//网络请求结果分发 } else { isSuccess = false; if(result != null) { if (result.ResponseMsg != null) { //TODO 异常消息推送 CDebug.Log("请求发生异常!========================================="); if (mOnNetExceptionHandler != null) mOnNetExceptionHandler(result.Code, result.ResponseMsg); } }else { CDebug.Log("处理返回值对象为NULL!"); } } return isSuccess; } public void OnNetDistributeRequestTimeOut(HttpRequest request) { } #endregion #region 属性 getter/setter public string MacAddress { get { if(mMacAddress == null) { NetworkInterface[] nis = NetworkInterface.GetAllNetworkInterfaces(); ObjectArray list = new ObjectArray(nis.Length); StringBuilder result = new StringBuilder(""); string str; int i = 0; int max = nis.Length; while (i < max) { str = nis[i].GetPhysicalAddress().ToString(); if (list.IndexOf(str) == -1 && str != "" && str != "00000000000000E0") { list.Add(str); result.Append(str); result.Append(","); } i++; } result.Remove(result.Length - 1, 1); mMacAddress = result.ToString(); } return mMacAddress; } } public string GameTypeParam { get { return mGameType.ToString(); } } public string Host { get { return mHost; } } public int pollingWaitingPlayerTimeMax { get { return mPWPTimeMax; } set { mPWPTimeMax = value; } } public int netTicTimeMax { get { return mNetTicTimeMax; } set { mNetTicTimeMax = value; } } public ObjectArray waitingPlayers { get { return mWaitingPlayers; } } public ObjectArray rankPlayers { get { return mRankPlayers; } } public int hID { get { return mHID; } } #endregion } }