2023-03-05 23:09:09 +08:00

522 lines
19 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Library.Common.Event;
using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Library.Exception;
using Milimoe.FunGame.Desktop.Controller;
using Milimoe.FunGame.Desktop.Library;
using Milimoe.FunGame.Desktop.Library.Component;
using Milimoe.FunGame.Desktop.Library.Interface;
using Milimoe.FunGame.Desktop.UI;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ListView;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
namespace Milimoe.FunGame.Desktop.Model
{
public class MainModel : IMain
{
public bool Connected => Socket != null && Socket.Connected;
private readonly Main Main;
private Task? ReceivingTask;
private Core.Library.Common.Network.Socket? Socket;
private bool IsReceiving = false;
public MainModel(Main main)
{
Main = main;
}
#region
public bool LogOut()
{
try
{
// 需要当时登录给的Key发回去确定是账号本人在操作才允许登出
if (Config.Guid_LoginKey != Guid.Empty)
{
if (Socket?.Send(SocketMessageType.Logout, Config.Guid_LoginKey) == SocketResult.Success)
{
return true;
}
}
else throw new CanNotLogOutException();
}
catch (Exception e)
{
ShowMessage.ErrorMessage("无法登出您的账号,请联系服务器管理员。", "登出失败", 5);
Main.GetMessage(e.GetErrorInfo());
Main.OnFailedLogoutEvent(new GeneralEventArgs());
Main.OnAfterLogoutEvent(new GeneralEventArgs());
}
return false;
}
public void Disconnect()
{
try
{
Socket?.Send(SocketMessageType.Disconnect, "");
}
catch (Exception e)
{
Main.GetMessage(e.GetErrorInfo());
Main.OnFailedDisconnectEvent(new GeneralEventArgs());
Main.OnAfterDisconnectEvent(new GeneralEventArgs());
}
}
public void Disconnected()
{
Disconnect();
}
public bool GetServerConnection()
{
try
{
// 获取服务器IP
string? ipaddress = (string?)Implement.GetFunGameImplValue(InterfaceType.IClient, InterfaceMethod.RemoteServerIP);
if (ipaddress != null)
{
string[] s = ipaddress.Split(':');
if (s != null && s.Length > 1)
{
Constant.Server_Address = s[0];
Constant.Server_Port = Convert.ToInt32(s[1]);
if (Connect() == ConnectResult.Success) return true; // 连接服务器
}
}
else
{
ShowMessage.ErrorMessage("查找可用的服务器失败!");
Config.FunGame_isRetrying = false;
throw new FindServerFailedException();
}
}
catch (Exception e)
{
Main.GetMessage(e.GetErrorInfo(), TimeType.None);
}
return false;
}
public ConnectResult Connect()
{
Main.OnBeforeConnectEvent(new GeneralEventArgs());
if (Constant.Server_Address == "" || Constant.Server_Port <= 0)
{
ShowMessage.ErrorMessage("查找可用的服务器失败!");
Main.OnFailedConnectEvent(new GeneralEventArgs());
Main.OnAfterConnectEvent(new GeneralEventArgs());
return ConnectResult.FindServerFailed;
}
try
{
if (Config.FunGame_isRetrying)
{
Main.GetMessage("正在连接服务器,请耐心等待。");
Config.FunGame_isRetrying = false;
Main.OnFailedConnectEvent(new GeneralEventArgs());
Main.OnAfterConnectEvent(new GeneralEventArgs());
return ConnectResult.CanNotConnect;
}
if (!Config.FunGame_isConnected)
{
Main.CurrentRetryTimes++;
if (Main.CurrentRetryTimes == 0) Main.GetMessage("开始连接服务器...", TimeType.General);
else Main.GetMessage("第" + Main.CurrentRetryTimes + "次重试连接服务器...");
// 超过重连次数上限
if (Main.CurrentRetryTimes + 1 > Main.MaxRetryTimes)
{
throw new CanNotConnectException();
}
// 与服务器建立连接
Socket?.Close();
Config.FunGame_isRetrying = true;
Socket = Core.Library.Common.Network.Socket.Connect(Constant.Server_Address, Constant.Server_Port);
if (Socket != null && Socket.Connected)
{
// 设置可复用Socket
RunTime.Socket = Socket;
// 发送连接请求
if (Socket.Send(SocketMessageType.Connect) == SocketResult.Success)
{
Task t = Task.Factory.StartNew(() =>
{
if (Receiving() == SocketMessageType.Connect)
{
Main.GetMessage("连接服务器成功请登录账号以体验FunGame。");
Main.UpdateUI(MainInvokeType.Connected);
StartReceiving();
while (true)
{
if (IsReceiving)
{
Main.OnSucceedConnectEvent(new GeneralEventArgs());
Main.OnAfterConnectEvent(new GeneralEventArgs());
break;
}
}
}
});
return ConnectResult.Success;
}
Socket?.Close();
Config.FunGame_isRetrying = false;
throw new CanNotConnectException();
}
}
else
{
Main.GetMessage("已连接至服务器,请勿重复连接。");
return ConnectResult.CanNotConnect;
}
}
catch (Exception e)
{
Main.GetMessage(e.GetErrorInfo(), TimeType.None);
Main.UpdateUI(MainInvokeType.SetRed);
Config.FunGame_isRetrying = false;
Task.Factory.StartNew(() =>
{
Main.OnFailedConnectEvent(new GeneralEventArgs());
Main.OnAfterConnectEvent(new GeneralEventArgs());
});
return ConnectResult.ConnectFailed;
}
return ConnectResult.CanNotConnect;
}
public bool Close()
{
try
{
if (Socket != null)
{
Socket.Close();
Socket = null;
}
if (ReceivingTask != null && !ReceivingTask.IsCompleted)
{
ReceivingTask.Wait(1);
ReceivingTask = null;
IsReceiving = false;
}
}
catch (Exception e)
{
Main.GetMessage(e.GetErrorInfo(), TimeType.None);
return false;
}
return true;
}
public void SetWaitConnectAndSetYellow()
{
throw new NotImplementedException();
}
public void SetWaitLoginAndSetYellow()
{
throw new NotImplementedException();
}
public void SetGreenAndPing()
{
throw new NotImplementedException();
}
public void SetGreen()
{
throw new NotImplementedException();
}
public void SetYellow()
{
throw new NotImplementedException();
}
public void SetRed()
{
throw new NotImplementedException();
}
public bool IntoRoom()
{
try
{
if (Socket?.Send(SocketMessageType.IntoRoom, Config.FunGame_Roomid) == SocketResult.Success)
return true;
else throw new CanNotIntoRoomException();
}
catch (Exception e)
{
Main.GetMessage(e.GetErrorInfo());
Main.OnFailedIntoRoomEvent(new GeneralEventArgs());
Main.OnAfterIntoRoomEvent(new GeneralEventArgs());
return false;
}
}
public bool Chat(string msg)
{
try
{
if (Socket?.Send(SocketMessageType.Chat, msg) == SocketResult.Success)
return true;
else throw new CanNotSendTalkException();
}
catch (Exception e)
{
Main.GetMessage(e.GetErrorInfo());
Main.OnFailedSendTalkEvent(new GeneralEventArgs());
Main.OnAfterSendTalkEvent(new GeneralEventArgs());
return false;
}
}
#endregion
#region
private void StartReceiving()
{
ReceivingTask = Task.Factory.StartNew(() =>
{
Thread.Sleep(100);
IsReceiving = true;
while (Socket != null && Socket.Connected)
{
Receiving();
}
});
Socket?.StartReceiving(ReceivingTask);
}
private object[] GetServerMessage()
{
if (Socket != null && Socket.Connected)
{
return Socket.Receive();
}
return new object[2] { SocketMessageType.Unknown, Array.Empty<object>() };
}
private SocketMessageType Receiving()
{
if (Socket is null) return SocketMessageType.Unknown;
SocketMessageType result = SocketMessageType.Unknown;
try
{
object[] ServerMessage = GetServerMessage();
SocketMessageType type = (SocketMessageType)ServerMessage[0];
object[] objs = (object[])ServerMessage[1];
result = type;
switch (type)
{
case SocketMessageType.Connect:
SocketHandler_Connect(objs);
break;
case SocketMessageType.GetNotice:
SocketHandler_GetNotice(objs);
break;
case SocketMessageType.Login:
SocketHandler_Login(objs);
break;
case SocketMessageType.CheckLogin:
SocketHandler_CheckLogin(objs);
RunTime.Login?.OnAfterLoginEvent(new GeneralEventArgs());
break;
case SocketMessageType.Logout:
SocketHandler_LogOut(objs);
break;
case SocketMessageType.Disconnect:
SocketHandler_Disconnect(objs);
break;
case SocketMessageType.HeartBeat:
if (Socket.Connected && Usercfg.LoginUser != null)
Main.UpdateUI(MainInvokeType.SetGreenAndPing);
break;
case SocketMessageType.IntoRoom:
SocketHandler_IntoRoom(objs);
break;
case SocketMessageType.QuitRoom:
break;
case SocketMessageType.Chat:
SocketHandler_Chat(objs);
break;
case SocketMessageType.Reg:
case SocketMessageType.CheckReg:
RunTime.Register?.SocketHandler(type, objs);
break;
case SocketMessageType.Unknown:
default:
break;
}
}
catch (Exception e)
{
// 报错中断服务器连接
Main.GetMessage(e.GetErrorInfo(), TimeType.None);
Main.UpdateUI(MainInvokeType.Disconnected);
Main.OnFailedConnectEvent(new GeneralEventArgs());
Close();
}
return result;
}
#endregion
#region SocketHandler
private void SocketHandler_Connect(object[] objs)
{
string msg = "";
Guid token = Guid.Empty;
if (objs.Length > 0) msg = NetworkUtility.ConvertJsonObject<string>(objs[0])!;
string[] strings = msg.Split(';');
string ServerName = strings[0];
string ServerNotice = strings[1];
Config.FunGame_ServerName = ServerName;
Config.FunGame_Notice = ServerNotice;
if (objs.Length > 1) token = NetworkUtility.ConvertJsonObject<Guid>(objs[1]);
Socket!.Token = token;
Config.Guid_Socket = token;
Main.GetMessage($"已连接服务器:{ServerName}。\n\n********** 服务器公告 **********\n\n{ServerNotice}\n\n");
// 设置等待登录的黄灯
Main.UpdateUI(MainInvokeType.WaitLoginAndSetYellow);
}
private void SocketHandler_GetNotice(object[] objs)
{
if (objs.Length > 0) Config.FunGame_Notice = NetworkUtility.ConvertJsonObject<string>(objs[0])!;
}
private void SocketHandler_Login(object[] objs)
{
Guid key = Guid.Empty;
string? msg = "";
// 返回一个Key再发回去给服务器就行了
if (objs.Length > 0) key = NetworkUtility.ConvertJsonObject<Guid>(objs[0]);
if (objs.Length > 1) msg = NetworkUtility.ConvertJsonObject<string>(objs[1]);
// 如果返回了msg说明验证错误。
if (msg != null && msg.Trim() != "")
{
ShowMessage.ErrorMessage(msg, "登录失败");
RunTime.Login?.OnFailedLoginEvent(new GeneralEventArgs());
RunTime.Login?.OnAfterLoginEvent(new GeneralEventArgs());
}
else
{
if (key != Guid.Empty)
{
Config.Guid_LoginKey = key;
LoginController.CheckLogin(key);
}
else
{
ShowMessage.ErrorMessage("登录失败!!", "登录失败", 5);
RunTime.Login?.OnFailedLoginEvent(new GeneralEventArgs());
RunTime.Login?.OnAfterLoginEvent(new GeneralEventArgs());
}
}
}
private void SocketHandler_LogOut(object[] objs)
{
Guid key = Guid.Empty;
string? msg = "";
// 返回一个Key如果这个Key是空的登出失败
if (objs != null && objs.Length > 0) key = NetworkUtility.ConvertJsonObject<Guid>(objs[0]);
if (objs != null && objs.Length > 1) msg = NetworkUtility.ConvertJsonObject<string>(objs[1]);
if (key != Guid.Empty)
{
Config.Guid_LoginKey = Guid.Empty;
Main.UpdateUI(MainInvokeType.LogOut, msg ?? "");
Main.OnSucceedLogoutEvent(new GeneralEventArgs());
}
else
{
ShowMessage.ErrorMessage("无法登出您的账号,请联系服务器管理员。", "登出失败", 5);
Main.OnFailedLogoutEvent(new GeneralEventArgs());
}
Main.OnAfterLogoutEvent(new GeneralEventArgs());
}
private void SocketHandler_CheckLogin(object[] objs)
{
// 返回的objs是该Login的User对象的各个属性
if (objs != null && objs.Length > 0)
{
// 创建User对象并返回到Main
Main.UpdateUI(MainInvokeType.SetUser, new object[] { Factory.New<User>(objs) });
RunTime.Login?.OnSucceedLoginEvent(new GeneralEventArgs());
return;
}
ShowMessage.ErrorMessage("登录失败!!", "登录失败", 5);
RunTime.Login?.OnFailedLoginEvent(new GeneralEventArgs());
}
private void SocketHandler_Disconnect(object[] objs)
{
string msg = "";
if (objs.Length > 0) msg = NetworkUtility.ConvertJsonObject<string>(objs[0])!;
Main.GetMessage(msg);
Main.UpdateUI(MainInvokeType.Disconnect);
Close();
Main.OnSucceedDisconnectEvent(new GeneralEventArgs());
Main.OnAfterDisconnectEvent(new GeneralEventArgs());
}
private void SocketHandler_IntoRoom(object[] objs)
{
string roomid = "";
if (objs.Length > 0) roomid = NetworkUtility.ConvertJsonObject<string>(objs[0])!;
if (roomid.Trim() != "" && roomid == "-1")
{
Main.GetMessage($"已连接至公共聊天室。");
}
else
{
Config.FunGame_Roomid = roomid;
}
Main.OnSucceedIntoRoomEvent(new GeneralEventArgs());
Main.OnAfterIntoRoomEvent(new GeneralEventArgs());
}
private void SocketHandler_Chat(object[] objs)
{
if (objs != null && objs.Length > 1)
{
string user = NetworkUtility.ConvertJsonObject<string>(objs[0])!;
string msg = NetworkUtility.ConvertJsonObject<string>(objs[1])!;
if (user != Usercfg.LoginUserName)
{
Main.GetMessage(msg, TimeType.None);
}
Main.OnSucceedSendTalkEvent(new GeneralEventArgs());
Main.OnAfterSendTalkEvent(new GeneralEventArgs());
return;
}
Main.OnFailedSendTalkEvent(new GeneralEventArgs());
Main.OnAfterSendTalkEvent(new GeneralEventArgs());
}
#endregion
}
}