2026-07-17 17:50:31 +08:00
|
|
|
|
using Assets.MyGame.Scripts.Net;
|
2026-05-27 19:47:06 +08:00
|
|
|
|
using Assets.MyGame.Scripts.Net.WebResponses;
|
2026-02-13 19:23:01 +08:00
|
|
|
|
using Assets.MyGame.Scripts.Net.WebResponses.ChineseChess;
|
2026-02-03 11:35:19 +08:00
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
|
using System;
|
2026-06-17 21:26:06 +08:00
|
|
|
|
using System.Collections.Generic;
|
2026-05-27 19:47:06 +08:00
|
|
|
|
using System.Text;
|
2026-03-09 09:25:01 +08:00
|
|
|
|
using Unity.VisualScripting;
|
2026-05-27 19:47:06 +08:00
|
|
|
|
using UnityEngine;
|
2026-02-03 11:35:19 +08:00
|
|
|
|
|
2026-02-26 11:05:56 +08:00
|
|
|
|
public partial class WebSocketSendList
|
2026-02-03 11:35:19 +08:00
|
|
|
|
{
|
2026-05-27 19:47:06 +08:00
|
|
|
|
public static string MakeKillFishSign(
|
|
|
|
|
|
string roomId,
|
|
|
|
|
|
string userId,
|
|
|
|
|
|
string fishNumber,
|
|
|
|
|
|
string fishId,
|
|
|
|
|
|
long gold,
|
|
|
|
|
|
long timespan,
|
|
|
|
|
|
string bulletId,
|
|
|
|
|
|
long timestamp,
|
|
|
|
|
|
string signKey
|
|
|
|
|
|
)
|
|
|
|
|
|
{
|
|
|
|
|
|
string rawStr = $"{roomId}|{userId}|{fishNumber}|{fishId}|{gold}|{timespan}|{bulletId}|{timestamp}";
|
|
|
|
|
|
return Sign(rawStr, signKey);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static string MakeFireCannonSign(string roomId, string userId, long gold, int count, long timestamp, string signKey)
|
|
|
|
|
|
{
|
|
|
|
|
|
string rawStr = $"{roomId}|{userId}|{gold}|{count}|{timestamp}";
|
|
|
|
|
|
Debug.Log($"生成签名的原始字符串:{rawStr}");
|
|
|
|
|
|
return Sign(rawStr, signKey);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static string Sign(string rawStr, string signKey)
|
|
|
|
|
|
{
|
|
|
|
|
|
string input = rawStr + "|" + signKey;
|
|
|
|
|
|
|
|
|
|
|
|
using (var md5 = System.Security.Cryptography.MD5.Create())
|
|
|
|
|
|
{
|
|
|
|
|
|
byte[] bytes = Encoding.UTF8.GetBytes(input);
|
|
|
|
|
|
byte[] hash = md5.ComputeHash(bytes);
|
|
|
|
|
|
|
|
|
|
|
|
// 转成 hex 字符串(前 8 位)
|
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
for (int i = 0; i < hash.Length; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
sb.Append(hash[i].ToString("x2"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return sb.ToString().Substring(0, 8);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-02-13 19:23:01 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取房间信息
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static void GetRoomListFish(int leave,int district)
|
|
|
|
|
|
{
|
|
|
|
|
|
WebSocketManager.Instance.Send(SocketType.room, "{\"type\":1,\"target\":\"GetRoomList\",\"invocationId\":\"1\",\"arguments\":[\"" + GameManager.Instance.user.id + "\"," + (int)GameManager.Instance.gameData.currGameType + "," + leave + ","+ district + "]}");
|
|
|
|
|
|
}
|
2026-05-27 19:47:06 +08:00
|
|
|
|
|
2026-02-03 11:35:19 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 打中鱼
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="roomId"></param>
|
|
|
|
|
|
/// <param name="userId"></param>
|
|
|
|
|
|
/// <param name="fishNumber">配置id</param>
|
|
|
|
|
|
/// <param name="fishId">唯一id</param>
|
2026-05-27 19:47:06 +08:00
|
|
|
|
public static void KillFish(
|
|
|
|
|
|
string roomId,
|
|
|
|
|
|
string userId,
|
|
|
|
|
|
string fishNumber,
|
|
|
|
|
|
string fishId,
|
|
|
|
|
|
int paoBei,
|
|
|
|
|
|
string bulletId,
|
|
|
|
|
|
string signKey
|
|
|
|
|
|
)
|
2026-02-03 11:35:19 +08:00
|
|
|
|
{
|
2026-05-27 19:47:06 +08:00
|
|
|
|
long timespan = BeijingTimeManager.Instance.CurrentTimestampMs; // 毫秒
|
|
|
|
|
|
long timestamp = timespan / 1000; // 秒级
|
|
|
|
|
|
|
|
|
|
|
|
// count 固定为 1
|
|
|
|
|
|
string sign = MakeKillFishSign(roomId, userId, fishNumber, fishId, paoBei, timespan, bulletId, timestamp, signKey);
|
|
|
|
|
|
|
|
|
|
|
|
var sendObj = new WebSocketSendList(
|
|
|
|
|
|
"KillFish",
|
|
|
|
|
|
roomId,
|
|
|
|
|
|
userId,
|
|
|
|
|
|
fishNumber,
|
|
|
|
|
|
fishId,
|
|
|
|
|
|
paoBei,
|
|
|
|
|
|
timespan,
|
|
|
|
|
|
bulletId,
|
|
|
|
|
|
timestamp,
|
|
|
|
|
|
sign
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2026-02-03 11:35:19 +08:00
|
|
|
|
WebSocketManager.Instance.Send(SocketType.game, JsonConvert.SerializeObject(sendObj));
|
|
|
|
|
|
}
|
2026-05-27 19:47:06 +08:00
|
|
|
|
/// <summary>
|
2026-07-18 14:39:25 +08:00
|
|
|
|
/// 真人玩家发射子弹(对接后端最新签名)
|
|
|
|
|
|
/// 服务端方法:Task<List<string>> FireCannon(roomId, userId, gold, count, timestamp, sign, extra)
|
|
|
|
|
|
/// 返回值 List<string> 为服务端生成的 bulletIds,通过 RoomFireNotice 广播给房间所有人
|
2026-05-27 19:47:06 +08:00
|
|
|
|
/// </summary>
|
2026-07-17 17:50:31 +08:00
|
|
|
|
/// <param name="roomId">房间ID</param>
|
|
|
|
|
|
/// <param name="userId">玩家ID</param>
|
2026-05-27 19:47:06 +08:00
|
|
|
|
/// <param name="gold">单价</param>
|
|
|
|
|
|
/// <param name="count">数量</param>
|
2026-07-18 14:39:25 +08:00
|
|
|
|
/// <param name="timestamp">秒级时间戳</param>
|
|
|
|
|
|
/// <param name="sign">签名(MD5 前8位)</param>
|
2026-07-17 17:50:31 +08:00
|
|
|
|
/// <param name="extra">附加数据(SyncGameData)</param>
|
2026-05-27 19:47:06 +08:00
|
|
|
|
public static void FireCannon(
|
|
|
|
|
|
string roomId,
|
|
|
|
|
|
string userId,
|
|
|
|
|
|
long gold,
|
|
|
|
|
|
int count,
|
2026-07-18 14:39:25 +08:00
|
|
|
|
long timestamp,
|
|
|
|
|
|
string sign,
|
|
|
|
|
|
object extra = null
|
2026-05-27 19:47:06 +08:00
|
|
|
|
)
|
|
|
|
|
|
{
|
|
|
|
|
|
var sendObj = new WebSocketSendList(
|
|
|
|
|
|
"FireCannon",
|
|
|
|
|
|
roomId,
|
|
|
|
|
|
userId,
|
|
|
|
|
|
gold,
|
|
|
|
|
|
count,
|
2026-07-18 14:39:25 +08:00
|
|
|
|
timestamp,
|
|
|
|
|
|
sign,
|
|
|
|
|
|
extra
|
2026-05-27 19:47:06 +08:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
WebSocketManager.Instance.Send(SocketType.game, JsonConvert.SerializeObject(sendObj));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-03 11:35:19 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 发射子弹
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="roomId"></param>
|
|
|
|
|
|
/// <param name="userId"></param>
|
|
|
|
|
|
/// <param name="gold">单价</param>
|
|
|
|
|
|
/// <param name="count">数量</param>
|
|
|
|
|
|
public static void ShootBullet(string roomId, string userId, int gold, int count)
|
|
|
|
|
|
{
|
|
|
|
|
|
var sendObj = new WebSocketSendList("ShootBullet", roomId, userId, gold, count);
|
|
|
|
|
|
WebSocketManager.Instance.Send(SocketType.game, JsonConvert.SerializeObject(sendObj));
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 链接登录界面ws
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="userId"></param>
|
|
|
|
|
|
public static void Bind(string userId)
|
|
|
|
|
|
{
|
|
|
|
|
|
var sendObj = new WebSocketSendList("Bind", userId);
|
|
|
|
|
|
WebSocketManager.Instance.Send(SocketType.login, JsonConvert.SerializeObject(sendObj));
|
|
|
|
|
|
}
|
2026-07-21 04:36:52 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 断线重连(必须先调用,重新加入房间前调用)
|
|
|
|
|
|
/// 对应服务端 FishGameHub.Reconnect(string userId)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static void Reconnect(string userId)
|
|
|
|
|
|
{
|
|
|
|
|
|
var sendObj = new WebSocketSendList("Reconnect", userId);
|
|
|
|
|
|
WebSocketManager.Instance.Send(SocketType.game, JsonConvert.SerializeObject(sendObj));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取玩家信息(结果通过 SendPlayerInfoResult 事件返回)
|
|
|
|
|
|
/// 对应服务端 FishGameHub.GetPlayerInfo(string roomId, string userId)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static void GetPlayerInfo(string roomId, string userId)
|
|
|
|
|
|
{
|
|
|
|
|
|
var sendObj = new WebSocketSendList("GetPlayerInfo", roomId, userId);
|
|
|
|
|
|
WebSocketManager.Instance.Send(SocketType.game, JsonConvert.SerializeObject(sendObj));
|
|
|
|
|
|
}
|
2026-02-03 11:35:19 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 加入房间
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="roomId"></param>
|
|
|
|
|
|
/// <param name="userId"></param>
|
|
|
|
|
|
/// <param name="level">房间等级</param>
|
2026-03-09 09:25:01 +08:00
|
|
|
|
public static void JoinRoom(string roomId, string userId, int sitID)
|
2026-02-03 11:35:19 +08:00
|
|
|
|
{
|
2026-03-09 09:25:01 +08:00
|
|
|
|
var sendObj = new WebSocketSendList("JoinRoom", roomId, userId, sitID);
|
2026-02-03 11:35:19 +08:00
|
|
|
|
WebSocketManager.Instance.Send(SocketType.game, JsonConvert.SerializeObject(sendObj));
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
2026-03-09 09:25:01 +08:00
|
|
|
|
/// 获取房间信息
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="roomId">房间id</param>
|
|
|
|
|
|
public static void GetRoomInfo(string roomId)
|
|
|
|
|
|
{
|
|
|
|
|
|
var sendObj = new WebSocketSendList("GetRoomInfo", roomId);
|
|
|
|
|
|
WebSocketManager.Instance.Send(SocketType.room, JsonConvert.SerializeObject(sendObj));
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
2026-02-03 11:35:19 +08:00
|
|
|
|
/// 使用道具
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="roomId"></param>
|
|
|
|
|
|
/// <param name="userId"></param>
|
|
|
|
|
|
/// <param name="propNumber">道具id</param>
|
|
|
|
|
|
/// <param name="diamond">道具消耗</param>
|
|
|
|
|
|
public static void UseProp(string roomId, string userId, string propNumber, int diamond)
|
|
|
|
|
|
{
|
|
|
|
|
|
var sendObj = new WebSocketSendList("UseProp", roomId, userId, propNumber, diamond);
|
|
|
|
|
|
WebSocketManager.Instance.Send(SocketType.game, JsonConvert.SerializeObject(sendObj));
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 离开房间
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="roomId"></param>
|
|
|
|
|
|
/// <param name="userId"></param>
|
|
|
|
|
|
public static void LeaveRoom(string roomId, string userId)
|
|
|
|
|
|
{
|
2026-03-18 17:26:14 +08:00
|
|
|
|
WebSocketManager.Instance.isGame=false;
|
2026-02-03 11:35:19 +08:00
|
|
|
|
var sendObj = new WebSocketSendList("LeaveRoom", roomId, userId);
|
|
|
|
|
|
WebSocketManager.Instance.Send(SocketType.game, JsonConvert.SerializeObject(sendObj));
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 更改炮倍
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="roomId"></param>
|
|
|
|
|
|
/// <param name="userId"></param>
|
|
|
|
|
|
/// <param name="multiple"></param>
|
|
|
|
|
|
public static void ChangeGunMultiple(string roomId, string userId,int multiple)
|
|
|
|
|
|
{
|
|
|
|
|
|
var sendObj = new WebSocketSendList("ChangeGunMultiple", roomId, userId, multiple);
|
|
|
|
|
|
WebSocketManager.Instance.Send(SocketType.game, JsonConvert.SerializeObject(sendObj));
|
|
|
|
|
|
}
|
2026-03-09 09:25:01 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-06-17 21:26:06 +08:00
|
|
|
|
/// 同步等级常量(秒)
|
2026-03-09 09:25:01 +08:00
|
|
|
|
/// </summary>
|
2026-06-17 21:26:06 +08:00
|
|
|
|
public const float SYNC_LV1 = 0.2f;
|
|
|
|
|
|
public const float SYNC_LV2 = 0.5f;
|
|
|
|
|
|
public const float SYNC_LV3 = 1f;
|
|
|
|
|
|
|
|
|
|
|
|
// 队列
|
|
|
|
|
|
private static float _syncLv1Timer;
|
|
|
|
|
|
private static float _syncLv2Timer;
|
|
|
|
|
|
private static float _syncLv3Timer;
|
|
|
|
|
|
private static Dictionary<int, SyncGameData> _syncLv1Cover = new Dictionary<int, SyncGameData>();
|
|
|
|
|
|
private static List<SyncGameData> _syncLv1Append = new List<SyncGameData>();
|
|
|
|
|
|
private static List<SyncGameData> _syncLv2Append = new List<SyncGameData>();
|
|
|
|
|
|
private static List<SyncGameData> _syncLv3Append = new List<SyncGameData>();
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>数据同步(自动按类型分级入队)</summary>
|
2026-03-09 09:25:01 +08:00
|
|
|
|
public static void SyncGameData(object obj)
|
|
|
|
|
|
{
|
2026-06-17 21:26:06 +08:00
|
|
|
|
var sgd = obj as SyncGameData;
|
|
|
|
|
|
if (sgd == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
SendImmediate(JsonConvert.SerializeObject(obj));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch (sgd.frameType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case FrameDataType.fireBullet:
|
2026-07-20 01:55:38 +08:00
|
|
|
|
case FrameDataType.rotateTurrect:
|
|
|
|
|
|
// ⭐ 开火/旋转实时发送,和开炮一样立即广播,保证炮台旋转流畅
|
2026-06-17 21:26:06 +08:00
|
|
|
|
SendImmediate(BuildJson(sgd));
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
case FrameDataType.changeAutoTarget:
|
|
|
|
|
|
_syncLv1Cover[sgd.sitPos] = sgd;
|
|
|
|
|
|
return;
|
|
|
|
|
|
case FrameDataType.randomDieFish:
|
|
|
|
|
|
_syncLv1Append.Add(sgd);
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
case FrameDataType.createFish:
|
|
|
|
|
|
case FrameDataType.changeTurretState:
|
|
|
|
|
|
case FrameDataType.changeTurret:
|
|
|
|
|
|
case FrameDataType.freezeFish:
|
|
|
|
|
|
_syncLv2Append.Add(sgd);
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2026-07-20 22:32:52 +08:00
|
|
|
|
case FrameDataType.requestSyncFish:
|
|
|
|
|
|
// ⭐ 新玩家加载完成的"请求同步鱼":立即发送,房主尽快响应广播
|
|
|
|
|
|
SendImmediate(BuildJson(sgd));
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2026-06-17 21:26:06 +08:00
|
|
|
|
default:
|
|
|
|
|
|
_syncLv3Append.Add(sgd);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>每帧调用,由 GameMainPanel.Update 驱动</summary>
|
|
|
|
|
|
public static void FlushSyncQueues(float dt)
|
|
|
|
|
|
{
|
|
|
|
|
|
_syncLv1Timer += dt;
|
|
|
|
|
|
if (_syncLv1Timer >= SYNC_LV1) { _syncLv1Timer = 0f; FlushLv1(); }
|
|
|
|
|
|
_syncLv2Timer += dt;
|
|
|
|
|
|
if (_syncLv2Timer >= SYNC_LV2) { _syncLv2Timer = 0f; FlushLv2(); }
|
|
|
|
|
|
_syncLv3Timer += dt;
|
|
|
|
|
|
if (_syncLv3Timer >= SYNC_LV3) { _syncLv3Timer = 0f; FlushLv3(); }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static void FlushLv1()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var kv in _syncLv1Cover) SendImmediate(BuildJson(kv.Value));
|
|
|
|
|
|
foreach (var sgd in _syncLv1Append) SendImmediate(BuildJson(sgd));
|
|
|
|
|
|
_syncLv1Cover.Clear();
|
|
|
|
|
|
_syncLv1Append.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
private static void FlushLv2()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var sgd in _syncLv2Append) SendImmediate(BuildJson(sgd));
|
|
|
|
|
|
_syncLv2Append.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
private static void FlushLv3()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var sgd in _syncLv3Append) SendImmediate(BuildJson(sgd));
|
|
|
|
|
|
_syncLv3Append.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static void SendImmediate(string json)
|
|
|
|
|
|
{
|
|
|
|
|
|
WebSocketManager.Instance.Send(SocketType.game, json);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static string BuildJson(object obj)
|
|
|
|
|
|
{
|
|
|
|
|
|
var sendObj = new WebSocketSendList
|
2026-03-09 09:25:01 +08:00
|
|
|
|
{
|
|
|
|
|
|
type = 1,
|
|
|
|
|
|
invocationId = "1",
|
|
|
|
|
|
target = "SyncGameData",
|
2026-06-17 21:26:06 +08:00
|
|
|
|
arguments = new System.Collections.Generic.List<object>
|
|
|
|
|
|
{
|
|
|
|
|
|
GameManager.Instance.gameData.currRoomData.roomId,
|
|
|
|
|
|
obj
|
|
|
|
|
|
}
|
2026-03-09 09:25:01 +08:00
|
|
|
|
};
|
2026-06-17 21:26:06 +08:00
|
|
|
|
return JsonConvert.SerializeObject(sendObj);
|
2026-03-09 09:25:01 +08:00
|
|
|
|
}
|
2026-02-03 11:35:19 +08:00
|
|
|
|
}
|