提交修改
This commit is contained in:
311
Assets/Scripts/Entry.cs
Normal file
311
Assets/Scripts/Entry.cs
Normal file
@@ -0,0 +1,311 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Network;
|
||||
using Newtonsoft.Json;
|
||||
using SimpleJSON;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public sealed class EntryComponent : Entity
|
||||
{
|
||||
public Entry Entry;
|
||||
}
|
||||
|
||||
public class Entry : MonoBehaviour
|
||||
{
|
||||
private static cfg.Tables _tables;
|
||||
public static cfg.Tables Tables => _tables;
|
||||
|
||||
private Scene _scene;
|
||||
private Session _session;
|
||||
|
||||
public GameObject LoginPanel;
|
||||
public GameObject ChatPanel;
|
||||
|
||||
public Text MessageText;
|
||||
public InputField PrivateText;
|
||||
public InputField UserName;
|
||||
public InputField SendMessageText;
|
||||
public Button LoginButton;
|
||||
public Button ExitButton;
|
||||
public Button BroadcastButton;
|
||||
public Button ChannelButton;
|
||||
public Button PrivateButton;
|
||||
|
||||
public Button SendButton1;
|
||||
public Button ChatNodeEventButton;
|
||||
|
||||
|
||||
void Start()
|
||||
{
|
||||
LoginPanel.SetActive(true);
|
||||
ChatPanel.SetActive(false);
|
||||
StartAsync().Coroutine();
|
||||
LoginButton.onClick.RemoveAllListeners();
|
||||
LoginButton.onClick.AddListener(() => { OnLoginButtonClick().Coroutine(); });
|
||||
ExitButton.onClick.RemoveAllListeners();
|
||||
ExitButton.onClick.AddListener(() => { OnExitButtonClick().Coroutine(); });
|
||||
SendButton1.onClick.RemoveAllListeners();
|
||||
SendButton1.onClick.AddListener(() => { OnSendButton1Click().Coroutine(); });
|
||||
BroadcastButton.onClick.RemoveAllListeners();
|
||||
BroadcastButton.onClick.AddListener(() => { OnBroadcastButtonClick().Coroutine(); });
|
||||
ChannelButton.onClick.RemoveAllListeners();
|
||||
ChannelButton.onClick.AddListener(() => { OnChannelButtonClick().Coroutine(); });
|
||||
PrivateButton.onClick.RemoveAllListeners();
|
||||
PrivateButton.onClick.AddListener(() => { OnPrivateButtonClick().Coroutine(); });
|
||||
}
|
||||
|
||||
private async FTask StartAsync()
|
||||
{
|
||||
LoadData();
|
||||
// 1. 初始化 Fantasy 框架
|
||||
await Fantasy.Platform.Unity.Entry.Initialize();
|
||||
|
||||
// 2. 创建一个 Scene (客户端场景)
|
||||
// Scene 是 Fantasy 框架的核心容器,所有功能都在 Scene 下运行
|
||||
// SceneRuntimeMode.MainThread 表示在 Unity 主线程运行
|
||||
_scene = await Scene.Create(SceneRuntimeMode.MainThread);
|
||||
_scene.AddComponent<EntryComponent>().Entry = this;
|
||||
}
|
||||
|
||||
private async FTask OnLoginButtonClick()
|
||||
{
|
||||
// 创建一个连接,这里是连接到目标的Gate服务器
|
||||
_session = _scene.Connect(
|
||||
"127.0.0.1:20001",
|
||||
NetworkProtocolType.KCP,
|
||||
() =>
|
||||
{
|
||||
Log.Debug("连接成功!");
|
||||
_session.AddComponent<SessionHeartbeatComponent>().Start(2000);
|
||||
},
|
||||
() => { Log.Debug("连接失败!"); },
|
||||
() => { Log.Debug("断开连接!"); },
|
||||
false, 5000);
|
||||
|
||||
// 发送登录的请求给服务器
|
||||
var response = (A2C_LoginResponse)await _session.Call(new C2A_LoginRequest()
|
||||
{
|
||||
Username = UserName.text,
|
||||
Password = UserName.text,
|
||||
LoginType = 1
|
||||
});
|
||||
|
||||
if (response.ErrorCode != 0)
|
||||
{
|
||||
Log.Error($"登录发生错误{response.ErrorCode}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ParseJWT(response.ToKen, out var payload))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_session = _scene.Connect(
|
||||
payload.Address,
|
||||
NetworkProtocolType.KCP,
|
||||
() =>
|
||||
{
|
||||
Log.Debug("连接成功!");
|
||||
_session.AddComponent<SessionHeartbeatComponent>().Start(2000);
|
||||
},
|
||||
() => { Log.Debug("连接失败!"); },
|
||||
() => { Log.Debug("断开连接!"); },
|
||||
false, 5000);
|
||||
|
||||
|
||||
// 发送登录请求到Gate服务器
|
||||
var loginResponse = (G2C_LoginResponse)await _session.Call(new C2G_LoginRequest()
|
||||
{
|
||||
ToKen = response.ToKen
|
||||
});
|
||||
if (loginResponse.ErrorCode != 0)
|
||||
{
|
||||
Log.Error($"登录发生错误{loginResponse.ErrorCode}");
|
||||
return;
|
||||
}
|
||||
|
||||
LoginPanel.SetActive(false);
|
||||
ChatPanel.SetActive(true);
|
||||
Log.Debug("登录成功!");
|
||||
}
|
||||
|
||||
private async FTask OnExitButtonClick()
|
||||
{
|
||||
// var response = (G2C_ExitResponse)await _session.Call(new C2G_ExitRequest());
|
||||
// if (response.ErrorCode != 0)
|
||||
// {
|
||||
// Log.Error($"退出游戏错误 ErrorCode:{response.ErrorCode}");
|
||||
// return;
|
||||
// }
|
||||
// LoginPanel.SetActive(true);
|
||||
// ChatPanel.SetActive(false);
|
||||
// Log.Debug("退出游戏成功!");
|
||||
}
|
||||
|
||||
private async FTask OnSendButton1Click()
|
||||
{
|
||||
await FTask.CompletedTask;
|
||||
// SendButton1.interactable = false;
|
||||
// var response = (Chat2C_SendMessageResponse) await _session.Call(new C2Chat_SendMessageRequest());
|
||||
// if (response.ErrorCode != 0)
|
||||
// {
|
||||
// Log.Error($"发送聊天消息失败 ErrorCode:{response.ErrorCode}");
|
||||
// return;
|
||||
// }
|
||||
// Log.Debug("发送聊天消息成功!");
|
||||
// SendButton1.interactable = true;
|
||||
}
|
||||
|
||||
private async FTask OnBroadcastButtonClick()
|
||||
{
|
||||
BroadcastButton.interactable = false;
|
||||
var tree = ChatTreeFactory.Broadcast(_scene);
|
||||
tree = tree.AddendPositionNode(SendMessageText.text, "勇者大陆", 121, 131, 111);
|
||||
|
||||
var response = (Chat2C_SendMessageResponse)await _session.Call(new C2Chat_SendMessageRequest()
|
||||
{
|
||||
ChatInfoTree = tree
|
||||
});
|
||||
if (response.ErrorCode != 0)
|
||||
{
|
||||
Log.Error($"发送聊天消息失败 ErrorCode:{response.ErrorCode}");
|
||||
}
|
||||
|
||||
BroadcastButton.interactable = true;
|
||||
}
|
||||
|
||||
private async FTask OnChannelButtonClick()
|
||||
{
|
||||
ChannelButton.interactable = false;
|
||||
var tree = ChatTreeFactory.Team(_scene);
|
||||
tree.ChatChannelId = 1;
|
||||
// tree = tree.AddendTextNode("你好,欢迎来到Fantasy Chat!").AddendLinkNode("点击这里http://www.fantasy.com.cn");
|
||||
var response = (Chat2C_SendMessageResponse)await _session.Call(new C2Chat_SendMessageRequest()
|
||||
{
|
||||
ChatInfoTree = tree
|
||||
});
|
||||
if (response.ErrorCode != 0)
|
||||
{
|
||||
Log.Error($"发送频道聊天消息失败 ErrorCode:{response.ErrorCode}");
|
||||
}
|
||||
|
||||
ChannelButton.interactable = true;
|
||||
}
|
||||
|
||||
private async FTask OnPrivateButtonClick()
|
||||
{
|
||||
PrivateButton.interactable = false;
|
||||
var tree = ChatTreeFactory.Private(_scene);
|
||||
tree.Target.Add(Convert.ToInt64(PrivateText.text));
|
||||
// tree = tree.AddendTextNode("你好,欢迎来到Fantasy Chat!").AddendLinkNode("点击这里http://www.fantasy.com.cn");
|
||||
|
||||
var response = (Chat2C_SendMessageResponse)await _session.Call(new C2Chat_SendMessageRequest()
|
||||
{
|
||||
ChatInfoTree = tree
|
||||
});
|
||||
if (response.ErrorCode != 0)
|
||||
{
|
||||
Log.Error($"发送私聊消息失败 ErrorCode:{response.ErrorCode}");
|
||||
}
|
||||
|
||||
PrivateButton.interactable = true;
|
||||
}
|
||||
|
||||
|
||||
#region Config
|
||||
|
||||
private void LoadData()
|
||||
{
|
||||
// 一行代码可以加载所有配置。 cfg.Tables 包含所有表的一个实例字段。
|
||||
_tables = new cfg.Tables(LoadJson);
|
||||
}
|
||||
|
||||
private static JSONNode LoadJson(string file)
|
||||
{
|
||||
//var json = File.ReadAllText($"{your_json_dir}/{file}.json", System.Text.Encoding.UTF8);
|
||||
//Assets/ResRaw/config/tb/tbbait.json
|
||||
var jsonAsset = AssetDatabase.LoadAssetAtPath<TextAsset>($"Assets/ResRaw/config/tb/{file}.json");
|
||||
return JSON.Parse(jsonAsset.text);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region JWT
|
||||
|
||||
public bool ParseJWT(string toKen, out Payload payloadData)
|
||||
{
|
||||
payloadData = null;
|
||||
|
||||
try
|
||||
{
|
||||
// JWT通常是由三个部分组成的,Header,Payload,Signature。
|
||||
var tokens = toKen.Split('.');
|
||||
|
||||
if (tokens.Length != 3)
|
||||
{
|
||||
Log.Error("Invalid JWT token");
|
||||
return false;
|
||||
}
|
||||
|
||||
// JWT的Payload不是标准的Base64格式,因为咱们C#的Convert要求是一个标准的Base64格式。
|
||||
// JWT的Payload是Base64URL格式,它里面的"-"替代成了"+","_"替代成了"/",需要把这些给还原成Base64格式
|
||||
var basePayload = tokens[1].Replace('-', '+').Replace('_', '/');
|
||||
// 因为Base64的编码长度需要是4的倍数,如果不是的话咱们需要把这个长度用=来填充,使其长度符合要求
|
||||
switch (basePayload.Length % 4)
|
||||
{
|
||||
// case 0:
|
||||
// {
|
||||
// // 如果这个余数是0,那就表示长度已经是4的倍数,那就没必要处理了。
|
||||
// break;
|
||||
// }
|
||||
// case 1:
|
||||
// {
|
||||
// // 如果这个余数是1,那就表示这个Base64格式是不正确的,不是咱们发放的token。
|
||||
// // 这样情况下,也不需要处理了。
|
||||
// break;
|
||||
// }
|
||||
case 2:
|
||||
{
|
||||
basePayload += "==";
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
basePayload += "=";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 将修复后的字符串解码为数组
|
||||
var basePayloadBytes = Convert.FromBase64String(basePayload);
|
||||
var payload = System.Text.Encoding.UTF8.GetString(basePayloadBytes);
|
||||
payloadData =
|
||||
JsonConvert.DeserializeObject<Payload>(payload); //JsonHelper.Deserialize<Payload>(payload);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public sealed class Payload
|
||||
{
|
||||
public long aId { get; set; }
|
||||
public string Address { get; set; }
|
||||
public uint SceneId { get; set; }
|
||||
public int exp { get; set; }
|
||||
public string iss { get; set; }
|
||||
public string aud { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user