Files
hjha-server/GameDAL/FriendRoom/Room.cs
xiaoou e9616125ce feat: initial commit - HJHA game server full source
6 major server modules (PdkFriendServer/GlobalSever/ServerCore/GameModule/GameNetModule) +
game logic (GameFix/GameDAL/ServerData) +
network layer (NetWorkMessage) +
data layer (ObjectModel) +
utilities (MrWu/Core/Config/CloudAPI/dll) +
adapters (zyxAdapter/base)

.NET 8.0 C# solution, 16 projects, 958 source files
2026-07-07 12:02:15 +08:00

1199 lines
44 KiB
C#

/*
* 作者:吴隆健
* 日期: 2019-04-22
* 时间: 13:20
*
*/
using System;
using Server.DB.Redis;
using StackExchange.Redis;
using MrWu.Debug;
using GameData;
using Server.Data;
using System.Data;
using Server.DB.Sql;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using GameMessage;
using Newtonsoft.Json;
using Server;
namespace GameDAL.FriendRoom
{
/// <summary>
/// 房间管理
/// </summary>
public static class Room
{
/// <summary>
/// 战斗数据保存的文件夹 --服务器目录
/// </summary>
public const string RoomFightPath = "RoomFightPath";
/// <summary>
/// 密码
/// </summary>
public const string pwdField = "pwd";
/// <summary>
/// 最大玩家数量
/// </summary>
public const string maxCntField = "maxCnt";
/// <summary>
/// 最小玩家数量
/// </summary>
public const string minCntField = "minCnt";
/// <summary>
/// 朋友房多少局
/// </summary>
public const string warCntField = "warCnt";
/// <summary>
/// 当前开战的是第几场
/// </summary>
public const string nowCntField = "nowCnt";
/// <summary>
/// 结束的局数
/// </summary>
public const string overCntField = "overCnt";
/// <summary>
/// 房间所属游戏
/// </summary>
public const string gameidField = "gameid";
/// <summary>
/// 服务器版本
/// </summary>
public const string serverVerField = "serVer";
/// <summary>
/// 0普通开 1代开房间 5竞技比赛创建房间
/// </summary>
public const string CreateStyleField = "createStyle";
/// <summary>
/// 创建房间id 如果是普通创建房间 则此id为玩家userid 竞技比赛创建则为竞技比赛id
/// </summary>
public const string CreateIdField = "CreateId";
/// <summary>
/// 创建房间的房卡数量
/// </summary>
public const string fangkaField = "Fangka";
/// <summary>
/// 座位标记
/// </summary>
public const string seatTagField = "seatTag";
/// <summary>
/// 房间规则
/// </summary>
public const string roomRuleField = "RoomRule";
/// <summary>
/// 创建时间
/// </summary>
public const string CreateTimeField = "CreateTime";
/// <summary>
/// userid
/// </summary>
public const string useridField = "Userid";
/// <summary>
/// 昵称
/// </summary>
public const string nickNameField = "nickName";
/// <summary>
/// 性别
/// </summary>
public const string sexField = "sex";
/// <summary>
/// 头像
/// </summary>
public const string photoField = "photo";
/// <summary>
/// 房主
/// </summary>
public const string fangzhuField = "fangzhu";
/// <summary>
/// 战斗id
/// </summary>
public const string fightField = "fightid";
/// <summary>
/// 玩家的分值
/// </summary>
public const string scorejsonField = "playerScore";
/// <summary>
/// 战斗座位
/// </summary>
public const string fightseatField = "seat";
/// <summary>
/// 是否拦截ip
/// </summary>
public const string interceptIpField = "interceptIp";
/// <summary>
/// 是否拦截不是微信的账号
/// </summary>
public const string interceptWeChatField = "interceptWeChat";
/// <summary>
/// 是否关闭
/// </summary>
public const string isCloseField = "closeField";
/// <summary>
/// 关闭时间
/// </summary>
public const string closeTimeField = "closeTime";
/// <summary>
/// 房间号
/// </summary>
public const string roomNumField = "roomNum";
/// <summary>
/// 战斗超时时间
/// </summary>
public const string wartimeOutField = "warTimeOut";
/// <summary>
/// 加入超时时间
/// </summary>
public const string jointimeOutField = "jointimeOut";
/// <summary>
/// 玩法的id
/// </summary>
public const string wayidField = "wayid";
/// <summary>
/// 拓展字段
/// </summary>
public const string exField = "ex";
/// <summary>
/// 拓展字段
/// </summary>
public const string ruleexField = "ruleEx";
/// <summary>
/// 房间的最大数量
/// </summary>
public const int MaxCnt = 1000000;
/// <summary>
/// 是否保存战斗数据到数据库
/// </summary>
//public static bool IsSaveFightToDB = false;
/// <summary>
/// 房间分布式锁
/// </summary>
public static DistributedLock roomlock = new DistributedLock(100);
/// <summary>
/// 获的一个房间号
/// </summary>
/// <returns></returns>
public static int GetRoomNum()
{
DateTime lastCreateTime = DateTime.Now;
string lastCreateNum = "000000";
try
{
var hes = redisManager.db.HashGetAll(RedisDictionary.lastRoomNum);
if (hes != null && hes.Length > 0)
{
foreach (var he in hes)
{
switch (he.Name)
{
case RedisDictionary.lastCreatRoomTime: //上次创建的时间
lastCreateTime = DateTime.Parse(he.Value);
break;
case RedisDictionary.lastRoomNum:
lastCreateNum = he.Value;
break;
}
}
}
}
catch (Exception e)
{
Debug.Error("7B69BB45-9B1A-49DF-BC81-3370D8CEDE59:" + e.ToString());
}
int lastCreateNum_ = int.Parse(lastCreateNum);
//时间差值,秒钟
int betweenTime = (int)(DateTime.Now - lastCreateTime).TotalSeconds;
//房间增量
int deltanum = betweenTime / 10 % 1000;
int roomNum_ = (lastCreateNum_ + deltanum) % MaxCnt;
while (roomNum_ == lastCreateNum_ || roomNum_ == 0)
{
roomNum_++;
roomNum_ = roomNum_ % MaxCnt;
}
try
{
HashEntry[] hhe = new HashEntry[2];
hhe[0] = new HashEntry(RedisDictionary.lastCreatRoomTime, DateTime.Now.ToString());
hhe[1] = new HashEntry(RedisDictionary.lastRoomNum, roomNum_);
redisManager.db.HashSetAsync(RedisDictionary.lastRoomNum, hhe, CommandFlags.FireAndForget);
}
finally
{
}
return roomNum_;
}
/// <summary>
/// 获取朋友房数据的key
/// </summary>
/// <returns></returns>
public static string GetWeiYiMaKey(string weiyima)
{
return RedisDictionary.friendRoomField + weiyima;
}
/// <summary>
/// 获取朋友房中玩家数据key
/// </summary>
/// <param name="weiyima"></param>
/// <param name="index"></param>
/// <returns></returns>
public static string GetPlayerKey(string weiyima, int index)
{
return RedisDictionary.friendRoomField + weiyima + ":" + index;
}
/// <summary>
/// 存储玩家所在的房间号以及唯一码
/// </summary>
/// <param name="userid"></param>
/// <returns></returns>
public static string GetPlayerNumKey(int userid)
{
return "Game:FriendRoom:Player:" + userid;
}
/// <summary>
/// 获取每局详情key
/// </summary>
/// <param name="weiyima"></param>
/// <param name="index"></param>
/// <returns></returns>
public static string GetBureauKey(string weiyima, int index)
{
return RedisDictionary.friendRoomField + weiyima + "." + index;
}
/// <summary>
/// 设置当前开战次数
/// </summary>
/// <param name="deskinfo"></param>
public static void SetNowCnt(DeskInfo deskinfo)
{
string key = GetWeiYiMaKey(deskinfo.weiyima);
redisManager.db.HashSet(key, nowCntField, deskinfo.nowCnt);
}
/// <summary>
/// 设置结束次数
/// </summary>
/// <param name="deskinfo"></param>
public static void SetOverCnt(DeskInfo deskinfo)
{
string key = GetWeiYiMaKey(deskinfo.weiyima);
redisManager.db.HashSet(key, overCntField, deskinfo.overCnt);
}
/// <summary>
/// 加载房间号
/// </summary>
/// <param name="roomnum">房间号</param>
/// <param name="weiyima">唯一码</param>
/// <returns></returns>
public static bool LoadPlayerNum(int userid, ref string roomnum, ref string weiyima)
{
string plNumKey = GetPlayerNumKey(userid);
var hes = redisManager.db.HashGetAll(plNumKey);
if (hes == null || hes.Length == 0)
return false;
int len = hes.Length;
for (int i = 0; i < len; i++)
{
switch (hes[i].Name)
{
case "num":
roomnum = hes[i].Value;
break;
case "weiyima":
weiyima = hes[i].Value;
break;
}
}
return true;
}
/// <summary>
/// 清楚玩家所在的房间号
/// </summary>
public static void ClearPlayerNum(int userid)
{
string plNumkey = GetPlayerNumKey(userid);
redisManager.db.KeyDelete(plNumkey);
}
/// <summary>
/// 获取房间的唯一码
/// </summary>
/// <param name="roomnum"></param>
/// <returns></returns>
public static bool GetWeiyima(int roomnum, ref string weiyima, ref ServerNode node)
{
string key = Roomkey(roomnum.ToString());
var hes = redisManager.db.HashGetAll(key);
if (hes == null || hes.Length == 0)
return false;
int len = hes.Length;
for (int i = 0; i < len; i++)
{
switch (hes[i].Name)
{
case "weiyima":
weiyima = hes[i].Value;
break;
case "server":
node = JsonPack.GetData<ServerNode>(hes[i].Value);
break;
}
}
return true;
}
/// <summary>
/// 保存玩家数据到redis中
/// </summary>
/// <param name="dskinfo"></param>
/// <param name="index"></param>
public static bool SavePlayerToRedis(DeskInfo dskinfo, int index)
{
DeskInfo.PlayerData pl = dskinfo.pls[index];
if (pl == null)
{
Debug.Error("程序错误....playerdata is null index:{0}", index);
return false;
}
string plNumKey = GetPlayerNumKey(pl.userid);
string key = GetPlayerKey(dskinfo.weiyima, index);
IDatabase db = redisManager.GetDataBase();
var tran = db.CreateTransaction();
tran.AddCondition(Condition.KeyNotExists(plNumKey));
tran.AddCondition(Condition.KeyNotExists(key));
var numhes = new HashEntry[2];
numhes[0] = new HashEntry("num", dskinfo.roomNum); //房间号
numhes[1] = new HashEntry("weiyima", dskinfo.weiyima); //唯一码
tran.HashSetAsync(plNumKey, numhes); //保存玩家的房间号以及唯一码
HashEntry[] hes = new HashEntry[6];
hes[0] = new HashEntry(useridField, pl.userid);
hes[1] = new HashEntry(fangzhuField, pl.fangzhu);
if (pl.nickName == null)
pl.nickName = string.Empty;
hes[2] = new HashEntry(nickNameField, pl.nickName);
if (pl.photo == null)
pl.photo = string.Empty;
hes[3] = new HashEntry(photoField, pl.photo);
hes[4] = new HashEntry(sexField, pl.sex);
hes[5] = new HashEntry("clubid", pl.ClubId);
tran.HashSetAsync(key, hes); //保存玩家数据
key = GetWeiYiMaKey(dskinfo.weiyima);
Debug.Info("key1:" + key + "," + plNumKey);
tran.AddCondition(Condition.KeyExists(key));
tran.HashSetAsync(key, seatTagField, JsonPack.GetJson(dskinfo.seat)); //保存房间数据中的座位信息
Debug.Log("key2:" + key);
return tran.Execute();
}
/// <summary>
/// 从redis中清楚玩家数据
/// </summary>
/// <param name="dskinfo"></param>
/// <param name="index"></param>
public static bool ClearPlayerToRedis(DeskInfo dskinfo, int index, int userid)
{
string key = GetPlayerKey(dskinfo.weiyima, index);
var db = redisManager.GetDataBase();
var tran = db.CreateTransaction();
tran.KeyDeleteAsync(key); //清空玩家数据
key = GetPlayerNumKey(userid);
tran.KeyDeleteAsync(key);
key = GetWeiYiMaKey(dskinfo.weiyima);
tran.AddCondition(Condition.KeyExists(key));
tran.HashSetAsync(key, seatTagField, JsonPack.GetJson(dskinfo.seat));
return tran.Execute();
}
/// <summary>
/// 保存单局详情_修改及保存
/// </summary>
/// <param name="deskinfo">桌子信息</param>
/// <param name="index"></param>
public static void SaveBureau(DeskInfo deskinfo, int index)
{
string key = GetBureauKey(deskinfo.weiyima, index);
redisManager.db.StringSet(key, JsonPack.GetJson(deskinfo.burs[index]));
}
/// <summary>
/// 保存牌局数据包
/// </summary>
/// <param name="weiyima"></param>
/// <param name="data"></param>
public static void SaveFightData(string weiyima, byte[] data)
{
FightDataManager.Instance.SaveFightData(weiyima,data);
}
public static void DelFightData(string weiyima)
{
FightDataManager.Instance.DelFightData(weiyima);
}
/// <summary>
/// 加载牌局数据包
/// </summary>
/// <param name="weiyima"></param>
/// <returns></returns>
public static byte[] LoadFightData(string weiyima,out bool isOld)
{
byte[] data = FightDataManager.Instance.LoadFightData(weiyima,out isOld);
return data;
}
/// <summary>
/// 加载战斗记录-回放用 --- todo 改成二进制存储
/// </summary>
/// <param name="weiyima">朋友房唯一码</param>
/// <param name="playCnt">玩的场次</param>
/// <param name="data">战斗数据</param>
public static void LoadFightRecord(string weiyima, int playCnt, out FightData data)
{
string key = RedisDictionary.friendRoomfightRecord + playCnt + ":" + weiyima;
//先找文本
string fileName = $"fightRecord/{key}";
fileName = fileName.Replace(":", "");
if (File.Exists(fileName))
{
try
{
string jsonData = File.ReadAllText(fileName);
data = JsonConvert.DeserializeObject<FightData>(jsonData);
File.Delete(fileName);
Debug.Info("读取回放数据!!");
return;
}
catch (Exception e)
{
Debug.Error($"加载战绩报错!{weiyima},{playCnt}" + e.Message);
}
}
var values = redisManager.db.ListRange(key);
if (values == null || values.Length == 0)
{
data = new FightData();
return;
}
else
{
data = new FightData();
try
{
int len = values.Length;
for (int i = 1; i < len; i++)
{
var dataone = JsonPack.GetData<fightdataone>(values[i]);
data.fightPack.Add(dataone);
}
}
catch (Exception e)
{
Debug.Error($"加载战斗数据-出现错误!!! {e.Message}");
}
}
}
/// <summary>
/// 设置总结算
/// </summary>
public static void SetSumBurs(DeskInfo deskinfo)
{
if (deskinfo == null) return;
//if (!deskinfo.isAllOver) return;
if (deskinfo.seat == null || deskinfo.seat.Length <= 0 || deskinfo.burs == null ||
deskinfo.burs.Count <= 0) return;
try
{
deskinfo.SumBurs.Clear();
int[] seat = new int[deskinfo.seat.Length];
decimal[] score = new decimal[seat.Length];
for (int i = 0; i < deskinfo.seat.Length; i++)
{
seat[i] = deskinfo.seat[i];
var num = deskinfo.GetTotalScore(seat[i]);
score[i] = num * (decimal)deskinfo.rule.peilv;
}
score = CalcCapping(score, deskinfo.rule.Capping);
for (int i = 0; i < seat.Length; i++)
{
DeskInfo.SummaryBureau temp = new DeskInfo.SummaryBureau { seat = seat[i], Score = score[i] };
deskinfo.SumBurs.Add(temp);
}
}
catch (Exception e)
{
Debug.Error($"SetSumBurs error:{e.Message},code:{e.StackTrace},Data info");
}
}
/// <summary>
/// 计算超过封顶的玩家,让赢的玩家均摊
/// </summary>
/// <param name="playScore"></param>
/// <param name="capping"></param>
/// <returns></returns>
public static decimal[] CalcCapping(decimal[] playScore, int capping)
{
if (capping <= 0) return playScore;
int len = playScore.Length;
decimal zongDuo = 0; //输的多出来的总数
decimal zongShu = 0; //超过封顶的玩家 输的总数
List<int> winIdx = new List<int>(); //赢钱人的下标
List<decimal> winJian = new List<decimal>(); //存储赢钱人平均摊的数值
for (int i = 0; i < len; i++)
{
var temp = Math.Abs(playScore[i]);
if (playScore[i] < 0 && temp > capping)
{
zongDuo += temp - capping;
playScore[i] = 0 - capping;
}
if (playScore[i] > 0)
{
zongShu += playScore[i];
winIdx.Add(i);
}
}
for (int i = 0; i < winIdx.Count - 1; i++)
{
var temp = zongDuo * playScore[winIdx[i]] / zongShu;
winJian.Add(Math.Round(temp, 2));
}
var temp1 = zongDuo - winJian.Sum();
winJian.Add(temp1);
for (int i = 0; i < winIdx.Count; i++)
{
playScore[winIdx[i]] = playScore[winIdx[i]] - winJian[i];
}
return playScore;
}
/// <summary>
/// 根据唯一码获取房间号
/// </summary>
/// <param name="weiyima">唯一码</param>
/// <returns>房间号</returns>
public static string GetRoomNum(string weiyima)
{
string key = GetWeiYiMaKey(weiyima);
return redisManager.db.HashGet(key, roomNumField);
}
/// <summary>
/// 加载房间数据_当前房间
/// </summary>
/// <param name="weiyima">唯一码</param>
/// <param name="data">房间数据</param>
/// <returns>是否加载成功</returns>
public static bool LoadRoom(string weiyima, out DeskInfo data)
{
string key = GetWeiYiMaKey(weiyima);
data = new DeskInfo();
DeskInfo dt = data;
dt.rule = new DeskRule();
DeskRule rule = dt.rule;
Func<bool> func = () =>
{
dt.weiyima = weiyima;
try
{
//获取朋友房数据 //朋友房基本数据
HashEntry[] hes = redisManager.db.HashGetAll(key);
if (hes == null || hes.Length <= 0)
return false;
foreach (var he in hes)
{
switch (he.Name)
{
case roomNumField:
dt.roomNum = he.Value;
break;
case pwdField:
rule.pwd = he.Value;
break;
case maxCntField:
rule.maxCnt = int.Parse(he.Value);
break;
case minCntField:
rule.minCnt = int.Parse(he.Value);
break;
case warCntField:
rule.warCnt = int.Parse(he.Value);
break;
case exField:
var ex = JsonPack.GetData<string[]>(he.Value);
rule.ex = ex;
break;
case ruleexField:
var exstr = he.value;
rule.RuleEx = string.IsNullOrEmpty(exstr)
? new DeskRuleEx()
: JsonPack.GetData<DeskRuleEx>(exstr);
break;
case "peilv":
rule.peilv = float.Parse(he.Value);
break;
case "Capping":
rule.Capping = int.Parse(he.value);
break;
case "Remarks":
rule.Remarks = he.value;
break;
case overCntField:
dt.overCnt = int.Parse(he.Value);
break;
case gameidField:
rule.game_serid = int.Parse(he.Value);
break;
case serverVerField:
dt.serverVer = int.Parse(he.Value);
break;
case CreateStyleField:
dt.creatStyle = int.Parse(he.Value);
break;
case CreateIdField:
dt.creatUserid = int.Parse(he.Value);
break;
case fangkaField:
dt.fangka = int.Parse(he.Value);
break;
case seatTagField:
dt.seat = JsonPack.GetData<int[]>(he.Value);
Debug.Info("座位号:" + he.Value);
break;
case roomRuleField:
dt.rule.roomrule = he.Value;
break;
case CreateTimeField:
dt.CreateTime = DateTime.Parse(he.Value);
break;
case nowCntField:
dt.nowCnt = int.Parse(he.Value);
break;
case interceptIpField:
rule.interceptIp = int.Parse(he.Value);
break;
case interceptWeChatField:
rule.interceptWeChat = int.Parse(he.Value);
break;
case isCloseField:
dt.isClose = int.Parse(he.Value);
break;
case closeTimeField:
dt.closeTime = DateTime.Parse(he.Value);
break;
case jointimeOutField:
dt.jointimeOutDis = DateTime.Parse(he.Value);
break;
case wartimeOutField:
dt.wartimeOutDis = DateTime.Parse(he.Value);
break;
case wayidField:
dt.wayid = he.Value;
break;
}
}
//RedisDictionary.friendRoomPlayerField+
dt.pls = new DeskInfo.PlayerData[rule.maxCnt];
dt.OnceFight = new int[rule.maxCnt];
for (int i = 0; i < rule.maxCnt; i++)
{
//加载玩家数据
string
plkey = GetPlayerKey(weiyima, i); // RedisDictionary.friendRoomPlayerField + weiyima+"."+i;
HashEntry[] plhes = redisManager.db.HashGetAll(plkey);
if (plhes == null || plhes.Length <= 0)
{
dt.pls[i] = null;
}
else
{
dt.pls[i] = new DeskInfo.PlayerData();
foreach (HashEntry he in plhes)
{
switch (he.Name)
{
case useridField:
dt.pls[i].userid = int.Parse(he.Value);
break;
case nickNameField:
dt.pls[i].nickName = he.Value;
break;
case sexField:
dt.pls[i].sex = int.Parse(he.Value);
break;
case photoField:
dt.pls[i].photo = he.Value;
break;
case fangzhuField:
dt.pls[i].fangzhu = int.Parse(he.Value);
break;
case "clubid":
dt.pls[i].ClubId = int.Parse(he.Value);
break;
}
}
}
}
//加载战斗记录
int cnt = dt.nowCnt != 0 ? dt.nowCnt : dt.overCnt;
for (int i = 0; i < cnt; i++)
{
string fightkey = GetBureauKey(weiyima, i); // RedisDictionary.friendRoomField+weiyima+i;
DeskInfo.Bureau bru = new DeskInfo.Bureau();
bru.id = i;
string jsonfihtrecord = redisManager.db.StringGet(fightkey);
if (jsonfihtrecord != null)
bru = JsonPack.GetData<DeskInfo.Bureau>(jsonfihtrecord);
dt.burs.Add(bru);
}
Debug.Info("桌子加载成功!");
return true;
}
catch (Exception e)
{
Debug.Error("加载房间号错误:" + e.ToString());
return false;
}
};
bool r = roomlock.LockRun(key, func, 5);
data.plsDis = new int[data.rule.maxCnt];
Room.SetSumBurs(data);
return r;
}
//创建房间移除房间修改房间只能又一个程序处理 其他程序只能读数据,不能改数据
/// <summary>
/// 创建房间 只负责redis数据
/// </summary>
/// <param name="data"></param>
public static bool CreateRoom(DeskInfo data, ServerNode node)
{
//房间号-> 唯一码 - 管理的模块
//朋友房的房间信息
//保证数据一致性
//先写房间号 - 唯一码 - 管理模块
string roomnum = data.roomNum;
string weiyima = data.weiyima;
//不存在才可以改,存在,不能改
var db = redisManager.GetDataBase();
string key = Roomkey(roomnum);
string datakey = RedisDictionary.friendRoomField + data.weiyima;
var tran = db.CreateTransaction();
tran.AddCondition(Condition.KeyNotExists(key)); //不存在才能执行事务
tran.AddCondition(Condition.KeyNotExists(datakey));
HashEntry[] hes = new HashEntry[2];
hes[0] = new HashEntry("weiyima", weiyima);
hes[1] = new HashEntry("server", JsonPack.GetJson(node));
tran.HashSetAsync(key, hes);
var datahes = GetDeskInfoHashEntry(data);
tran.HashSetAsync(datakey, datahes.ToArray()); //保存朋友房数据
Debug.Info("创建朋友房:" + key + "," + datakey);
return tran.Execute();
}
/// <summary>
/// 获取桌子信息
/// </summary>
private static List<HashEntry> GetDeskInfoHashEntry(DeskInfo data)
{
List<HashEntry> datahes = new List<HashEntry>();
datahes.Add(new HashEntry(roomNumField, data.roomNum));
DeskRule rule = data.rule;
if (rule.pwd == null)
rule.pwd = string.Empty;
datahes.Add(new HashEntry(pwdField, rule.pwd));
datahes.Add(new HashEntry(maxCntField, rule.maxCnt));
datahes.Add(new HashEntry(minCntField, rule.minCnt));
datahes.Add(new HashEntry(warCntField, rule.warCnt));
datahes.Add(new HashEntry(nowCntField, data.nowCnt));
datahes.Add(new HashEntry(overCntField, data.overCnt));
datahes.Add(new HashEntry(gameidField, rule.game_serid));
datahes.Add(new HashEntry(serverVerField, data.serverVer));
datahes.Add(new HashEntry(CreateStyleField, data.creatStyle));
datahes.Add(new HashEntry(CreateIdField, data.creatUserid));
datahes.Add(new HashEntry(fangkaField, data.fangka));
datahes.Add(new HashEntry(seatTagField, JsonPack.GetJson(data.seat)));
datahes.Add(new HashEntry(roomRuleField, data.rule.roomrule));
datahes.Add(new HashEntry(CreateTimeField, data.CreateTime.ToString()));
datahes.Add(new HashEntry(interceptIpField, rule.interceptIp));
datahes.Add(new HashEntry(interceptWeChatField, rule.interceptWeChat));
datahes.Add(new HashEntry(isCloseField, data.isClose));
datahes.Add(new HashEntry(closeTimeField, data.closeTime.ToString()));
datahes.Add(new HashEntry(exField, JsonPack.GetJson(data.rule.ex)));
datahes.Add(new HashEntry(ruleexField, data.rule.RuleExStr));
datahes.Add(new HashEntry("peilv", rule.peilv));
datahes.Add(new HashEntry("Capping", rule.Capping));
datahes.Add(new HashEntry("Remarks", rule.Remarks == null ? "" : rule.Remarks.ToString()));
datahes.Add(new HashEntry(wartimeOutField, data.wartimeOutDis.ToString()));
datahes.Add(new HashEntry(jointimeOutField, data.jointimeOutDis.ToString()));
if (data.wayid != null)
datahes.Add(new HashEntry(wayidField, data.wayid.ToString()));
return datahes;
}
/// <summary>
/// 重新写入房间
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static bool RenewRoom(DeskInfo data)
{
string roomnum = data.roomNum;
string weiyima = data.weiyima;
//不存在才可以改,存在,不能改
var db = redisManager.GetDataBase();
string key = Roomkey(roomnum);
string datakey = RedisDictionary.friendRoomField + data.weiyima;
var datahes = GetDeskInfoHashEntry(data);
db.HashSetAsync(datakey, datahes.ToArray()); //保存朋友房数据
return true;
}
/// <summary>
/// 移除房间 ->先删房间主体->删除房间玩家数据->玩家详情
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static bool DeleteRoom(DeskInfo data)
{
if (!data.noWar)
{
//开战过保存到数据库
Task.Factory.StartNew(() =>
{
SaveRoomData(data);
SaveRoomPlayerData(data);
});
}
var db = redisManager.GetDataBase();
var tran = db.CreateTransaction();
//删除玩家的被锁的 房间号-对应的唯一码
//删除房间号-被锁的唯一码
//删除房间详细数据
//删除玩家数据
//删除每局详情,删除玩家详情
string key = Roomkey(data.roomNum);
tran.KeyDeleteAsync(key); //房间号-对应的唯一码
int len = data.pls.Length;
for (int i = 0; i < len; i++)
{
if (data.pls[i] == null) continue;
string plkey = GetPlayerNumKey(data.pls[i].userid);
tran.KeyDeleteAsync(plkey); //清楚玩家所在的房间号以及对应的唯一码
int index = -1;
int count = data.seat.Length; //玩家玩家详细数据
for (int j = 0; j < count; j++)
{
if (data.seat[j] == i)
{
index = i;
break;
}
}
if (index < 0)
{
Debug.Error("未找到玩家位置!");
continue;
}
string pldatakey = GetPlayerKey(data.weiyima, index);
tran.KeyDeleteAsync(pldatakey);
}
//删除房间详细数据
string datakey = RedisDictionary.friendRoomField + data.weiyima;
tran.KeyDeleteAsync(datakey);
DelFightData(data.weiyima);
// string fightdatakey = GetFightDataKey(data.weiyima);
// tran.KeyDeleteAsync(fightdatakey);
//Debug.Error("解散游戏数据!" + data.overCnt + "," + fightdatakey);
for (int i = 0; i < data.overCnt + 1; i++)
{
string bureaukey = GetBureauKey(data.weiyima, i);
tran.KeyDeleteAsync(bureaukey);
}
return tran.Execute();
}
/// <summary>
/// 保存房间基本数据
/// </summary>
static void SaveRoomData(DeskInfo data)
{
DeskRule rule = data.rule;
var sql = GameDB.Instance.BeginSetProcedureParameter(dbbase.game2018, "SaveRoomData202408");
GameDB.Instance.AddProdureParameters(sql, "@weiyima", SqlDbType.Char, data.weiyima);
GameDB.Instance.AddProdureParameters(sql, "@roomnum", SqlDbType.Char, data.roomNum);
GameDB.Instance.AddProdureParameters(sql, "@maxcnt", SqlDbType.Int, rule.maxCnt);
GameDB.Instance.AddProdureParameters(sql, "@mincnt", SqlDbType.Int, rule.minCnt);
GameDB.Instance.AddProdureParameters(sql, "@warcnt", SqlDbType.Int, rule.warCnt);
GameDB.Instance.AddProdureParameters(sql, "@nowcnt", SqlDbType.Int, data.nowCnt);
GameDB.Instance.AddProdureParameters(sql, "@overcnt", SqlDbType.Int, data.overCnt);
GameDB.Instance.AddProdureParameters(sql, "@gameid", SqlDbType.Int, rule.game_serid);
GameDB.Instance.AddProdureParameters(sql, "@serverVer", SqlDbType.Int, data.serverVer);
GameDB.Instance.AddProdureParameters(sql, "@createStyle", SqlDbType.Int, data.creatStyle);
GameDB.Instance.AddProdureParameters(sql, "@createid", SqlDbType.Int, data.creatUserid);
GameDB.Instance.AddProdureParameters(sql, "@fangka", SqlDbType.Int, data.fangka);
GameDB.Instance.AddProdureParameters(sql, "@interceptIp", SqlDbType.Int, rule.interceptIp);
GameDB.Instance.AddProdureParameters(sql, "@interceptWeChat", SqlDbType.Int, rule.interceptWeChat);
byte[] bts = System.Text.Encoding.UTF8.GetBytes(data.rule.roomrule);
GameDB.Instance.AddProdureParameters(sql, "@roomrule", SqlDbType.Image, bts); //json的base64数据
GameDB.Instance.AddProdureParameters(sql, "@createTime", SqlDbType.DateTime, data.CreateTime);
GameDB.Instance.AddProdureParameters(sql, "@closeTime", SqlDbType.DateTime, data.closeTime);
GameDB.Instance.AddProdureParameters(sql, "@ex", SqlDbType.Text, JsonPack.GetJson(data.rule.ex));
GameDB.Instance.AddProdureParameters(sql, "@ruleEx", SqlDbType.Text, data.rule.RuleExStr);
GameDB.Instance.AddProdureParameters(sql, "@peilv", SqlDbType.Float, rule.peilv);
GameDB.Instance.AddProdureParameters(sql, "@Capping", SqlDbType.Int, rule.Capping);
GameDB.Instance.AddProdureParameters(sql, "@Remarks", SqlDbType.VarChar,
rule.Remarks == null ? "" : rule.Remarks);
GameDB.Instance.EndAddProdureParameters(sql);
}
/// <summary>
/// 保存玩家数据
/// </summary>
static void SaveRoomPlayerData(DeskInfo data)
{
int len = data.pls.Length;
for (int i = 0; i < len; i++)
{
if (data.pls[i] == null) continue; //这个位置没人
var sql = GameDB.Instance.BeginSetProcedureParameter(dbbase.game2018, "SaveRoom_PlayerData2024");
GameDB.Instance.AddProdureParameters(sql, "@weiyima", SqlDbType.Char, data.weiyima);
GameDB.Instance.AddProdureParameters(sql, "@playeridx", SqlDbType.Int, i);
GameDB.Instance.AddProdureParameters(sql, "@userid", SqlDbType.Int, data.pls[i].userid);
GameDB.Instance.AddProdureParameters(sql, "@nickName", SqlDbType.NChar, data.pls[i].nickName);
GameDB.Instance.AddProdureParameters(sql, "@sex", SqlDbType.Int, data.pls[i].sex);
GameDB.Instance.AddProdureParameters(sql, "@clubid", SqlDbType.Int, data.pls[i].ClubId);
byte[] bts = Encoding.UTF8.GetBytes(data.pls[i].photo);
GameDB.Instance.AddProdureParameters(sql, "@photo", SqlDbType.Image, bts);
GameDB.Instance.AddProdureParameters(sql, "@fangzhu", SqlDbType.Int, data.pls[i].fangzhu);
long allScore = 0;
foreach (var item in data.burs)
{
allScore += item.playScore[i];
}
GameDB.Instance.AddProdureParameters(sql, "@allScore", SqlDbType.Int, allScore);
GameDB.Instance.AddProdureParameters(sql, "@gameid", SqlDbType.Int, data.rule.game_serid);
GameDB.Instance.EndAddProdureParameters(sql);
}
}
/// <summary>
/// 保存战斗数据
/// </summary>
/// <param name="deskinfo"></param>
/// <param name="data"></param>
/// <param name="style">结束类型</param>
public static void SaveFightRecord(DeskInfo deskinfo, FightData data, int style = -1)
{
//ClearFightRecord(deskinfo.weiyima, deskinfo.burs.Count);
if (data == null)
return;
Debug.Info("保存战斗记录到数据库!");
//string jsondata = JsonPack.GetJson(data);
int idx = deskinfo.burs.Count;
int index = idx - 1;
if (index < 0)
{
Debug.Warning("未开战过,无需保存!");
return;
}
int lx = deskinfo.creatStyle;
var playScore = deskinfo.burs[index].playScore;
//string score = JsonPack.GetJson(playScore);
var seatd = deskinfo.burs[index].seat;
//string seat = JsonPack.GetJson(seatd);
string weiyima = deskinfo.weiyima;
if (lx == 5 || lx == 0)
{
RoomFightData temp = new RoomFightData { playScore = playScore, seat = seatd, data = data, style = style };
FightRecordManager.Instance.SaveFightInfo(weiyima, temp, idx);
}
}
/// <summary>
/// 房间号key 里面保存着,管理房间的模块以及房间号对应的唯一码
/// </summary>
/// <param name="roomnum">房间号</param>
/// <returns>返回值</returns>
public static string Roomkey(string roomnum)
{
return "Game:FriendRoom:RoomNum:" + roomnum;
}
public static string GetClubFightKey(int userId)
{
return $"ClubFightLock:{userId}";
}
/// <summary>
/// 锁住俱乐部玩家
/// </summary>
/// <param name="userid"></param>
/// <param name="serId"></param>
public static void LockClubFightPlayer(List<int> userid, int serId)
{
try
{
var ts = TimeSpan.FromHours(1);
IBatch batch = redisManager.db.CreateBatch();
for (int i = 0; i < userid.Count; i++)
{
batch.StringSetAsync(GetClubFightKey(userid[i]), serId, ts);
}
batch.Execute();
}
catch (Exception e)
{
Debug.Error($"LockClubFightPlayer Error:{e.Message}");
}
}
}
}