Files
5.24BuYu/Assets/MyGame/Scripts/Net/WebSocketSendList_Fish.cs
T
2026-09-10 01:07:35 +08:00

391 lines
14 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 Assets.MyGame.Scripts.Net;
using Assets.MyGame.Scripts.Net.WebResponses;
using Assets.MyGame.Scripts.Net.WebResponses.ChineseChess;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
using Unity.VisualScripting;
using UnityEngine;
public partial class WebSocketSendList
{
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);
}
}
/// <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 + "]}");
}
/// <summary>
/// 打中鱼
/// </summary>
/// <param name="roomId"></param>
/// <param name="userId"></param>
/// <param name="fishNumber">配置id</param>
/// <param name="fishId">唯一id</param>
public static void KillFish(
string roomId,
string userId,
string fishNumber,
string fishId,
int paoBei,
string bulletId,
string signKey
)
{
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
);
var jsonStr = JsonConvert.SerializeObject(sendObj);
NetLog.Log($"扣钱:发送打中鱼请求: {jsonStr}");
WebSocketManager.Instance.Send(SocketType.game, jsonStr);
}
/// <summary>
/// 真人玩家发射子弹(对接后端最新签名)
/// 服务端方法:Task<List<string>> FireCannon(roomId, userId, gold, count, timestamp, sign, extra)
/// 返回值 List<string> 为服务端生成的 bulletIds,通过 RoomFireNotice 广播给房间所有人
/// </summary>
/// <param name="roomId">房间ID</param>
/// <param name="userId">玩家ID</param>
/// <param name="gold">单价</param>
/// <param name="count">数量</param>
/// <param name="timestamp">秒级时间戳</param>
/// <param name="sign">签名(MD5 前8位)</param>
/// <param name="extra">附加数据(SyncGameData)</param>
public static void FireCannon(
string roomId,
string userId,
long gold,
int count,
long timestamp,
string sign,
object extra = null
)
{
var sendObj = new WebSocketSendList(
"FireCannon",
roomId,
userId,
gold,
count,
timestamp,
sign,
extra
);
Debug.Log($"扣钱:发送开炮请求: {JsonConvert.SerializeObject(sendObj)}");
WebSocketManager.Instance.Send(SocketType.game, JsonConvert.SerializeObject(sendObj));
}
/// <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));
}
/// <summary>
/// 用户拒绝返回断线房间(LoginHub)
/// 登录后若收到 PendingRoomNotice,用户选择"离开"时调用
/// 服务端清理旧房间残留
/// </summary>
public static void DismissPendingRoom(string userId)
{
var sendObj = new WebSocketSendList("DismissPendingRoom", userId);
WebSocketManager.Instance.Send(SocketType.login, JsonConvert.SerializeObject(sendObj));
}
/// <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));
}
/// <summary>
/// 加入房间
/// </summary>
/// <param name="roomId"></param>
/// <param name="userId"></param>
/// <param name="level">房间等级</param>
public static void JoinRoom(string roomId, string userId, int sitID)
{
var sendObj = new WebSocketSendList("JoinRoom", roomId, userId, sitID);
WebSocketManager.Instance.Send(SocketType.game, JsonConvert.SerializeObject(sendObj));
}
/// <summary>
/// 获取房间信息
/// </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>
/// 使用道具
/// </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>
/// 使用鱼雷(FishGameHub.UseTorpedo):服务端扣 1 个鱼雷库存,按配置区间+权重随机得金币并直接加钱。
/// 结果以事件为准(项目惯例不读方法返回值 long newGold):
/// 1. TorpedoResultNotice 房间广播(所有人播放爆奖:随机炸死场上小鱼 + 红包分包爆金币)
/// 2. LoginHub AssetUpdated 推给使用者本人(金币权威值刷新)
/// </summary>
/// <param name="roomId">房间ID</param>
/// <param name="userId">玩家ID</param>
/// <param name="propNumber">鱼雷编号(如 "50001",与 gameConfig.propConfig 的 number 对应)</param>
public static void UseTorpedo(string roomId, string userId, string propNumber)
{
var sendObj = new WebSocketSendList("UseTorpedo", roomId, userId, propNumber);
NetLog.Log($"鱼雷:发送使用请求: {JsonConvert.SerializeObject(sendObj)}");
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)
{
WebSocketManager.Instance.isGame=false;
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));
}
/// <summary>
/// 玩家挂机(对应服务端 SetPlayerAfkNEW)
/// 服务端会向房间组广播 PlayerAfkNotice 事件
/// </summary>
public static void SetPlayerAfk(string roomId, string userId)
{
var sendObj = new WebSocketSendList("SetPlayerAfkNEW", roomId, userId);
WebSocketManager.Instance.Send(SocketType.game, JsonConvert.SerializeObject(sendObj));
}
/// <summary>
/// 取消挂机(对应服务端 CancelPlayerAfkNEW)
/// 服务端会向房间组广播 PlayerCancelAfkNotice 事件,并通过 OnFishSpawn(type=sync) 同步当前鱼
/// </summary>
public static void CancelPlayerAfk(string roomId, string userId)
{
var sendObj = new WebSocketSendList("CancelPlayerAfkNEW", roomId, userId);
WebSocketManager.Instance.Send(SocketType.game, JsonConvert.SerializeObject(sendObj));
}
/// <summary>
/// 同步等级常量(秒)
/// </summary>
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>
public static void SyncGameData(object obj)
{
var sgd = obj as SyncGameData;
if (sgd == null)
{
SendImmediate(JsonConvert.SerializeObject(obj));
return;
}
switch (sgd.frameType)
{
case FrameDataType.fireBullet:
case FrameDataType.rotateTurrect:
// ⭐ 开火/旋转实时发送,和开炮一样立即广播,保证炮台旋转流畅
SendImmediate(BuildJson(sgd));
return;
case FrameDataType.changeAutoTarget:
_syncLv1Cover[sgd.sitPos] = sgd;
return;
case FrameDataType.randomDieFish:
_syncLv1Append.Add(sgd);
return;
// createFish=3 已废弃:鱼创建改由服务端 OnFishSpawn 下发
case FrameDataType.changeTurretState:
case FrameDataType.changeTurret:
case FrameDataType.changeZhanShen:
case FrameDataType.freezeFish:
case FrameDataType.biaoQing:
_syncLv2Append.Add(sgd);
return;
// requestSyncFish=11 已废弃:鱼同步改由服务端 OnFishSpawn(type=sync) 下发
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
{
type = 1,
invocationId = "1",
target = "SyncGameData",
arguments = new System.Collections.Generic.List<object>
{
GameManager.Instance.gameData.currRoomData.roomId,
obj
}
};
return JsonConvert.SerializeObject(sendObj);
}
}