Files
hjha-server/GameModule/FriendRoom/FriendRoomManager.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

1792 lines
66 KiB
C#
Raw Permalink 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 System;
using GameDAL.FriendRoom;
using Server.Data.Module;
using Server.Data;
using GameData;
using Server.Pack;
using MrWu.Debug;
using Server.MQ;
using Game.Player;
using MrWu.Basic;
using System.Collections;
using System.Threading.Tasks;
using System.Collections.Generic;
using StackExchange.Redis;
using System.Linq;
using GameDAL;
using GameMessage;
using Server.AliyunSDK.SLSLog;
using Server.Config;
namespace Server
{
/// <summary>
/// 朋友房管理
/// </summary>
public partial class FriendRoomManager
{
/// <summary>
/// 实例
/// </summary>
public static FriendRoomManager instance { get; private set; }
private FriendRoomManager()
{
int len = allDesks.Length;
for (int i = 0; i < len; i++)
{
allDesks[i] = new Dictionary<int, Desk>();
}
}
static FriendRoomManager()
{
instance = new FriendRoomManager();
}
/// <summary>
/// 朋友房所在的厅
/// </summary>
private TingManager_Friend ting;
/// <summary>
/// 朋友房所在的城堡
/// </summary>
private RoomManager_Friend room;
/// <summary>
/// 朋友房的桌子
/// </summary>
public readonly Dictionary<int, Desk>[] allDesks = new Dictionary<int, Desk>[10];
/// <summary>
/// 初始化
/// </summary>
/// <param name="room"></param>
/// <param name="ting"></param>
public void Init(RoomManager room, TingManager ting)
{
this.room = room as RoomManager_Friend;
this.ting = ting as TingManager_Friend;
}
/// <summary>
/// 得到一个新的房间号
/// </summary>
/// <returns></returns>
private int GetNewRoomNum()
{
int roomnum = Room.GetRoomNum();
return CheckRoom(roomnum, 0);
}
/// <summary>
/// 检查房间号是否可用 循环检查连续100个房间检查到可用即返回
/// </summary>
/// <param name="roomNum">房间号</param>
/// <param name="checkCount">检查次数</param>
/// <returns>小于0表示未查到可用房间(这时候应该把修改上次检查房间的值,以便下次检查) 大于表示查到某房间可用</returns>
private int CheckRoom(int roomNum, int checkCount)
{
if (checkCount >= 100) //没有查询到
return -1;
checkCount++;
string weiyima = null;
ServerNode node = null;
if (!Room.GetWeiyima(roomNum, ref weiyima, ref node))
{
//房间号可用
return roomNum;
}
else
{
DeskInfo dt = null;
if (Room.LoadRoom(weiyima, out dt))
{
int isSendDis = dt.CheckDisBank();
if (isSendDis > 0)
{
//发送解散命令
PackHead head = PackHead.Create(ServerPackAgreement.disbank);
if (ServerHeart.instanece.IsDie(node.id, node.nodeNum))
{
Debug.Error("管理该房间的模块不在线!");
}
else
{
GlobalMQ.instance.DeliveryOne(node,
GlobalMQ.CreateMessage(head,
JsonPack.GetJson(new KeyValuePair<int, int>(roomNum, 2 + isSendDis))), true);
Debug.Warning("发送解散命令!" + roomNum);
}
head.Dispose();
head = null;
}
}
else
{
Debug.Warning("房间数据未加载成功!" + weiyima);
}
do
{
roomNum++;
roomNum = roomNum % Room.MaxCnt;
} while (roomNum == 0); //房间号从1开始
return CheckRoom(roomNum, checkCount); // 继续找
}
}
/// <summary>
/// 玩家退出
/// </summary>
/// <param name="userid"></param>
private bool QuitGame(int userid)
{
var tmp = PlayerCollection.Instance.FindPlayerByUserId(userid);
if (tmp == null)
{
Debug.Error("玩家退出未找到玩家:" + userid);
return false;
}
else
GameManager.instance.QuitGame(tmp, "QuitGame");
return true;
}
/// <summary>
/// 获取朋友房房间号
/// </summary>
/// <param name="head"></param>
/// <param name="rmdata"></param>
/// <returns>true 表示可以创建</returns>
private bool GetFriendRoomNum(PackHead head, CreateRoomPack rmdata)
{
//判断是否被锁,被锁,提示玩家被锁,并提示玩家去被锁的游戏
try
{
int roomnum = GetNewRoomNum(); //房间号
if (roomnum < 0)
{
//服务器爆满,创建失败,回包给玩家 提示玩家
GeneralSendPack.SendErrorInfo_Socket(head.userid, 0, 3, head.GetUtil());
if (rmdata.isAuto == 1)
{
QuitGame(head.userid);
}
return false;
}
else
{
Debug.Info("创建的房间号:" + roomnum + "," + rmdata.deskinfo.weiyima);
//按照房间号分发给模块处理,如果是本模块的直接处理
rmdata.deskinfo.roomNum = roomnum.ToString();
return true;
}
}
catch (Exception e)
{
Debug.Error("C480D7D2-B680-4321-924F-5C8AF7DAA2B6:" + e.ToString());
GeneralSendPack.SendErrorInfo_Socket(head.userid, 1, 37, head.GetUtil());
return false;
}
}
/// <summary>
/// 处理创建朋友房的包
/// </summary>
/// <param name="pack">包裹</param>
public void CreatFriendRoom(GamePack pack)
{
if (ting == null)
{
Debug.Error("游戏未开启朋友房功能!");
return;
}
PackHead head = pack.Head;
CreateRoomPack rmdata = JsonPack.GetData<CreateRoomPack>(pack.JsonData);
if (head == null || rmdata == null)
{
Debug.Error("客户端发送的数据有问题!创建失败!");
return;
}
//判断是否被锁,被锁,提示玩家被锁,并提示玩家去被锁的游戏
if (GetFriendRoomNum(head, rmdata))
CreatRoomLogin(head, rmdata, false, true);
}
/// <summary>
/// 俱乐部踢出玩家
/// </summary>
/// <returns>状态码</returns>
public int DoClubOutPlayer(string weiyima, int userId)
{
string roomnumStr = Room.GetRoomNum(weiyima);
int roomnum = 0;
if (!int.TryParse(roomnumStr, out roomnum))
{
return MessageErrCode.KickOutPlayerOfDesk_NoDesk;
}
Desk desk = FindDesk(roomnum);
if (desk == null || desk.deskinfo.weiyima != weiyima)
{
return MessageErrCode.KickOutPlayerOfDesk_NoDesk;
}
if (!desk.deskinfo.noWar)
{
return MessageErrCode.KickOutPlayerOfDesk_GameInWar;
}
for (int i = 0; i < desk.Count; i++)
{
if (desk[i] == null) continue;
if (desk[i].userid == userId)
{
PackHead headp = PackHead.Create();
headp.userid = userId;
headp.packlx = GamePackAgreement.autoTipInfo;
headp.otherString = new string[] { "您被管理员踢出房间!" };
GeneralSendPack.SendPackToPlayer(headp, desk[i], null);
GameManager.instance.DoComBack(desk[i]);
headp.Dispose();
break;
}
}
return MessageErrCode.Success;
}
/// <summary>
/// 竞技比赛踢出玩家
/// </summary>
/// <param name="pack"></param>
public void DoClubOutPlayer(GamePack pack)
{
var head = pack.Head;
string weiyima = head.otherString[0];
int userid = head.otherInt[0];
string roomnumStr = Room.GetRoomNum(weiyima);
int roomnum = 0;
if (!int.TryParse(roomnumStr, out roomnum))
{
head.transfer = ServerPackAgreement.OutPlayer;
head.packlx = ServerPackAgreement.TransFerHttp;
head.otherString = new string[] { "房间不存在!"};
GlobalMQ.instance.DeliveryOne(head.GetUtil(),
GlobalMQ.CreateMessage(head, null), true);
return;
}
Desk desk = FindDesk(roomnum);
if (desk == null || desk.deskinfo.weiyima != weiyima)
{
head.transfer = ServerPackAgreement.OutPlayer;
head.packlx = ServerPackAgreement.TransFerHttp;
head.otherString = new string[] { "房间不存在!"};
GlobalMQ.instance.DeliveryOne(head.GetUtil(),
GlobalMQ.CreateMessage(head, null), true);
return;
}
if (!desk.deskinfo.noWar)
{
head.transfer = ServerPackAgreement.OutPlayer;
head.packlx = ServerPackAgreement.TransFerHttp;
head.otherString = new string[] { "桌子已开战,踢出失败!"};
GlobalMQ.instance.DeliveryOne(head.GetUtil(),
GlobalMQ.CreateMessage(head, null), true);
return;
}
for (int i = 0; i < desk.Count; i++)
{
if (desk[i] == null) continue;
if (desk[i].userid == userid)
{
PackHead headp = PackHead.Create();
headp.userid = userid;
headp.packlx = GamePackAgreement.autoTipInfo;
headp.otherString = new string[] { "您被管理员踢出房间!" };
GeneralSendPack.SendPackToPlayer(headp, desk[i], null);
GameManager.instance.DoComBack(desk[i]);
head.Dispose();
break;
}
}
head.transfer = ServerPackAgreement.OutPlayer;
head.packlx = ServerPackAgreement.TransFerHttp;
head.otherString = new string[] { "踢出成功!"};
GlobalMQ.instance.DeliveryOne(head.GetUtil(),
GlobalMQ.CreateMessage(head, null), true);
}
public void QuitGameJoinOther(GamePack pack)
{
var head = pack.Head;
if (head.otherInt == null || head.otherInt.Length <= 0)
{
SendManager.SendErrotInfo_Http(head, 0, "数据错误!");
return;
}
var player = PlayerCollection.Instance.FindPlayerByUserId(head.userid);
if (player == null)
{
Debug.Error("未找到玩家!" + head.userid);
SendManager.SendErrotInfo_Http(head, 0, "未找到玩家!");
return;
}
JoinFriendRoom jfr = JsonPack.GetData<JoinFriendRoom>(pack.JsonData);
if (head == null || jfr == null)
{
Debug.Error("客户端发来的数据有问题,加入玩法失败!");
return;
}
PlayerState playerState = (PlayerState)player.state;
if (playerState == PlayerState.Desk || playerState == PlayerState.Ready)
{
if (string.IsNullOrEmpty(player.friendWeiYiMa) || player.friendRoomNum == 0)
{
SendManager.SendErrotInfo_Http(head, 0, $"你不在朋友房,不能切换房间!");
}
else
{
//玩家退出当前游戏
GameManager.instance.DoComBack(player);
//去处理进入房间
head.packlx = head.otherInt[0];
int dealModuleId = head.packlx / Game.Data.GameData.PackCardInt;
Debug.Log("转发给游戏服务器:" + head.packlx);
GlobalMQ.instance.DeliveryEveryOne(dealModuleId, GlobalMQ.CreateMessage(head, jfr), true);
}
}
else
{
SendManager.SendErrotInfo_Http(head, 0, $"当前状态{playerState}不能切换玩法!");
}
}
/// <summary>
/// 竞技比赛会长解散房间
/// </summary>
public int ClubDisBankCmd(string weiyima)
{
string roomnumStr = Room.GetRoomNum(weiyima);
int roomnum = 0;
if (!int.TryParse(roomnumStr, out roomnum))
{
return MessageErrCode.ClubDisbandNotFindDesk;
}
Desk desk = FindDesk(roomnum);
if (desk == null || desk.deskinfo.weiyima != weiyima)
{
return MessageErrCode.ClubDisbandNotFindDesk;
}
DisBank(desk, 7);
return MessageErrCode.Success;
}
/// <summary>
/// 竞技比赛会长解散房间
/// </summary>
/// <param name="pack"></param>
public void ClubDisBankCmd(GamePack pack)
{
var head = pack.Head;
string weiyima = head.otherString[0];
string roomnumStr = Room.GetRoomNum(weiyima);
int roomnum = 0;
if (!int.TryParse(roomnumStr, out roomnum))
{
SendManager.SendErrotInfo_Http(head, 2, 74);
return;
}
Desk desk = FindDesk(roomnum);
if (desk == null || desk.deskinfo.weiyima != weiyima)
{
SendManager.SendErrotInfo_Http(head, 2, 74);
return;
}
DisBank(desk, 7);
SendManager.SendErrotInfo_Http(head, 2, 75);
}
/// <summary>
/// 竞技比赛因玩家比赛积分不够解散桌子
/// </summary>
/// <param name="pack"></param>
public void ClubMatchDisBankByBurs(GamePack pack)
{
var head = pack.Head;
string weiyima = head.otherString[0];
string roomnumStr = Room.GetRoomNum(weiyima);
int roomnum = 0;
if (!int.TryParse(roomnumStr, out roomnum))
{
return;
}
Desk desk = FindDesk(roomnum);
if (desk == null || desk.deskinfo.weiyima != weiyima)
{
return;
}
DisBank(desk, 8);
}
/// <summary>
/// 竞技比赛创建桌子
/// </summary>
/// <param name="pack"></param>
public void DoClubCreateDesk(GamePack pack)
{
if (ting == null)
{
Debug.Error("游戏未开启朋友房功能!");
return;
}
PackHead head = pack.Head;
JoinFriendRoom jfr = JsonPack.GetData<JoinFriendRoom>(pack.JsonData);
if (head == null || jfr == null)
{
Debug.Error("客户端发来的数据有问题,加入玩法失败!");
return;
}
DeskInfo dskinfo = new DeskInfo();
dskinfo.wayid = jfr.way.weiyima;
dskinfo.creatStyle = 5;
dskinfo.creatUserid = jfr.way.Clubid;
dskinfo.rule = jfr.way.dskrule;
if (dskinfo.rule.RuleEx == null)
dskinfo.rule.RuleEx = new DeskRuleEx();
dskinfo.rule.RuleEx.ReadyTimeout = jfr.ReadyTimeOut;
CreateRoomPack crp = new CreateRoomPack();
crp.deskinfo = dskinfo;
crp.deviceInfo = jfr.deviceInfo;
crp.isAuto = jfr.isAuto;
crp.ClubId = jfr.ClubId;
crp.TaskId = jfr.TaskId;
//获取到房间号,去创建房间
if (instance.GetFriendRoomNum(head, crp))
{
instance.CreatRoomLogin(head, crp, true, true);
}
}
public async Task JoinClubDesk(GamePack pack)
{
PackHead head = pack.Head;
JoinFriendRoom jfr = JsonPack.GetData<JoinFriendRoom>(pack.JsonData);
if (head == null || jfr == null)
{
Debug.Error("客户端发来的数据有问题,加入玩法失败!");
return;
}
if (DoingUserIds.Contains(head.userid))
{
Debug.Error($"正在处理别的事务:{head.userid}");
GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.ClubJoinDeskDoing);
return;
}
if (ting == null)
{
Debug.Error("游戏未开启朋友房功能!");
GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.ClubJoinDeskNotOpenFriend);
return;
}
int userid = head.userid;
try
{
DoingUserIds.Add(userid);
//有则尝试加入房间!
//先把房间找到->
string strRoomNum = Room.GetRoomNum(jfr.joinweiyima);
Debug.Info("找到房间:" + strRoomNum + "," + jfr.joinweiyima);
//管理该房间的节点
ServerNode node = null;
string weiyima = null;
//拿到房间号,先看本地有没有,没有的话则加载起来
int roomnum = 0;
if (int.TryParse(strRoomNum, out roomnum))
{
//有房间号
if (Room.GetWeiyima(roomnum, ref weiyima, ref node))
{
//拿到唯一码
if (weiyima == jfr.joinweiyima)
{
//唯一码一致
if (!GameBase.instance.myUtil.Equals(node))
{
//交给管理模块处理
GlobalMQ.instance.DeliveryOne(node, GlobalMQ.CreateMessage(head, jfr), true);
}
else
{
//本模块处理
//没在本地加载到本地
Debug.Info("本地处理");
DoJoinFriendRoom djfr = new DoJoinFriendRoom(head,
new JoinRoom(roomnum.ToString(), weiyima) { deviceinfo = jfr.deviceInfo }, jfr,
false, true);
await djfr.Start();
if (!djfr.result)
{
//进入失败 再来一次
/*
jfr.lastjoinweiyima = weiyima;
jfr.joinweiyima = null;
*/
Debug.Log("加入失败的提示:" + djfr.errinfo);
if (jfr.TaskId <= 0)
{
if (string.IsNullOrEmpty(djfr.errinfo))
{
SendManager.SendErrotInfo_Http(head, 1, 73);
}
else
{
SendManager.SendErrotInfo_Http(head, 0, djfr.errinfo);
}
}
else
{
GeneralSendPack.SendJoinDeskResult(jfr.TaskId, djfr.errorCode);
}
/*
head.packlx = GlobalManager.instance.myUtil.id * 10000 + head.packlx;
GlobalMQ.instance.DeliveryOne(node, GlobalMQ.CreateMessage(head, jfr), true);
*/
Debug.Warning("进入失败,发包再试!" + head.ip);
}
else
{
if (jfr.TaskId <= 0)
{
//把玩家拉入桌子
head.transfer = ServerPackAgreement.ReConnection;
head.packlx = ServerPackAgreement.TransFerHttp;
head.otherInt = new int[] { ServerConfigManager.Instance.ClientId };
GlobalMQ.instance.DeliveryOne(head.GetUtil(),
GlobalMQ.CreateMessage(head, null),
true);
}
else
{
GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.Success);
}
}
}
return;
}
}
}
}
finally
{
DoingUserIds.Remove(userid);
}
}
/// <summary>
/// 处理加入玩法包
/// </summary>
/// <param name="pack"></param>
public void DoWanFa(GamePack pack)
{
PackHead head = pack.Head;
JoinFriendRoom jfr = JsonPack.GetData<JoinFriendRoom>(pack.JsonData);
if (head == null || jfr == null)
{
Debug.Error("客户端发来的数据有问题,加入玩法失败!");
return;
}
if (ting == null)
{
Debug.Error("加入玩法失败,游戏未开启朋友房功能!");
GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.ClubJoinDeskNotOpenFriend);
return;
}
JoinWanFa djfr = new JoinWanFa(head, jfr);
djfr.Start(head);
}
/// <summary>
/// 处理加入房间包
/// </summary>
/// <param name="pack"></param>
public async Task DoJoinRoom(GamePack pack)
{
if (ting == null)
{
Debug.Error("加入房间失败,游戏未开启朋友房功能!");
return;
}
PackHead head = pack.Head;
JoinRoom jr = JsonPack.GetData<JoinRoom>(pack.JsonData);
if (head == null || jr == null)
{
Debug.Error("客户端发来的数据有问题,加入房间失败!");
return;
}
DoJoinFriendRoom djfr = new DoJoinFriendRoom(head, jr, null, true, false);
await djfr.Start();
if (!djfr.result)
{
head.otherString = new string[] { djfr.errinfo };
head.packlx = GamePackAgreement.TransFerPack;
head.transfer = GameSeverAgreement.notJoinFriendRoom;
GlobalMQ.instance.DeliveryOne(head.GetUtil(), GlobalMQ.CreateMessage(head), true);
}
/*
* TTTT补: 加入房间房间的处理修改,需要外部发包通知
*
*
* */
}
/// <summary>
/// 处理回放
/// </summary>
/// <param name="pack"></param>
[Obsolete("过时,不使用")]
public void DoHuiFang(GamePack pack)
{
//过时,不使用
//Task task = Task.Factory.StartNew(
// () =>
// {
// FightRecordData frd = JsonPack.GetData<FightRecordData>(pack.jsondata);
// frd.data = Room.LoadFightRecord(frd.weiyima, frd.index);
// pack.head.packlx = GameSeverAgreement.friendfightdata;
// //回放数据可能是空!
// GameNet.SendPack_Userid(pack.head.GetModuleUtil(), pack.head, frd);
// }
//);
}
/// <summary>
/// 创建房间并登陆
/// </summary>
/// <param name="head"></param>
/// <param name="data"></param>
protected async Task CreatRoomLogin(PackHead head, CreateRoomPack data, bool isClub, bool isCheckDoing)
{
Debug.Info("创建房间 赔率:" + data.deskinfo.rule.peilv);
await new FriendRoomManager.CreateRoom(head, head.userid, data, isClub, isCheckDoing).Start();
}
/// <summary>
/// 解散房间包
/// </summary>
/// <param name="pk"></param>
public void DisBankDesk(GamePack pk)
{
if (ting == null)
{
Debug.Error("朋友房未开启!");
return;
}
if (pk.pl.tingid != ting.id)
{
Debug.Error("解散房间失败,没有这个房间!" + ting.id);
return;
}
DisBank(pk.pl);
}
/// <summary>
/// 请求解散包
/// </summary>
public void placeDisBank(GamePack pk)
{
placeDisBank(pk.pl);
}
/// <summary>
/// 请求解散回复包
/// </summary>
/// <param name="pk"></param>
public void DisReponse(GamePack pk)
{
bool dis = JsonPack.GetData<bool>(pk.JsonData);
DisReponse(pk.pl, dis, false);
}
/// <summary>
/// 解散房间命令
/// </summary>
public void DisBankCmd(int roomnum, int style)
{
//先判断房间存在不存在,再判断是否是过期房间
//满足条件,解散房间
if (ting != null)
{
Desk desk = FindDesk(roomnum);
if (desk == null)
{
Debug.Warning("无此房间,可能已经被解散了!");
}
else
{
//判断房间是否过期解散
if (desk.deskinfo == null)
{
Debug.Error("大错误,桌子数据为空!");
return;
}
if (style == 7)
{
Debug.Info("收到强制解散房间命令!");
DisBank(desk, style);
}
else
{
int isDisBank = desk.deskinfo.CheckDisBank();
if (isDisBank > 0)
{
Debug.Info("检查解散房间!");
//解散
DisBank(desk, 2 + isDisBank);
}
else
{
Debug.Warning("收到假的解散指令!");
}
}
}
}
else
{
Debug.Error("未开启朋友房,收到解散指令!");
}
}
/// <summary>
/// 获取玩家的桌子
/// </summary>
/// <param name="pl"></param>
/// <returns></returns>
public Desk GetPlayerDesk(PlayerDataAsyc pl)
{
//内存中如果没有桌子
Desk desk = FindDesk(pl.friendRoomNum);
if (desk != null)
return desk;
//去数据库中加载桌子
if (LoadFriendRoom(pl.friendRoomNum, pl.friendWeiYiMa))
{
desk = FindDesk(pl.friendRoomNum); //再从内存中加载起来
}
return desk;
}
/// <summary>
/// 加载房间
/// </summary>
/// <returns></returns>
protected bool LoadFriendRoom(int roomnum, string weiyima)
{
DeskInfo dskInfo = null;
//释放房间
void FreeRoom()
{
//没开启朋友房
Debug.Info("没开启朋友房!");
string _weiyima = null;
ServerNode node = null;
if (Room.GetWeiyima(roomnum, ref _weiyima, ref node)
&& weiyima == _weiyima)
{
if (Room.LoadRoom(_weiyima, out dskInfo))
{
//把数据从硬盘上加载起来
Debug.Info("加载朋友房数据:删除他!");
Desk.DisBank(dskInfo);
}
}
}
if (ting == null)
{
Debug.Error("未开启朋友房!");
FreeRoom(); //朋友房未开启,释放房间
return false;
}
//加载朋友房到内存
Desk dsk = FindDesk(roomnum);
if (dsk == null)
{
//内存中没有--去加载朋友房
Debug.Log("没找到这个朋友房:" + roomnum);
//去数据库中拿
DeskInfo dskinfo;
if (Room.LoadRoom(weiyima, out dskinfo))
{
//桌子数据处理完成!
Debug.Info($"加载朋友房数据! {dskinfo.weiyima}");
LoadDesk(dskinfo);
}
else
{
//数据库中也没有
return false;
}
}
return true;
}
private void SetPlayerScoreRecord(DeskInfo deskInfo)
{
try
{
if (!deskInfo.isAllOver || deskInfo.creatStyle != 5 || string.IsNullOrEmpty(deskInfo.wayid))
{
return;
}
LuckPlayerManager.FightScore[] fightScore = new LuckPlayerManager.FightScore[deskInfo.seat.Length];
for (int i = 0; i < deskInfo.seat.Length; i++)
{
fightScore[i] = new LuckPlayerManager.FightScore()
{
UserId = deskInfo.pls[i].userid,
Value = (int)deskInfo.SumBurs[i].Score
};
FriendRoomStatistics.Instance.AddSessionFight(deskInfo.wayid, deskInfo.rule.peilv,
deskInfo.pls[i].userid, (int)deskInfo.SumBurs[i].Score);
}
LuckPlayerManager.Instance.AddScoreRecord(deskInfo.wayid, deskInfo.rule.peilv, deskInfo.overCnt,
fightScore);
}
catch (Exception e)
{
Debug.Error($"SetPlayerScoreRecord:{e.Message}");
}
}
/// <summary>
/// 解散桌子逻辑
/// </summary>
/// <param name="desk">要解散的桌子</param>
/// <param name="style"> 1局数打完解散 2开战过-玩家申请解散 3超时解散(24小时未打完) 4超时解散(1小时内还没满员) 5房主解散 6玩法被删除 7竞技比赛管理解散房间 8因小局分不够解散 9托管自动解散</param>
public void DisBank(Desk desk, int style)
{
// 上报
if (desk.deskinfo != null && !desk.deskinfo.noWar)
{
desk.AddWarTime(); // 重新计算一下战局时长,防止漏计算
List<StatisticsTrackingLogData> eLogs = new List<StatisticsTrackingLogData>();
for (int i = 0; i < desk.PlayerCnt; i++)
{
if (desk[i] != null)
{
// 用户游玩时长
eLogs.Add(StatisticsTrackingLogData.Create(
desk[i].userid.ToString(),
EventTrackConst.GameFriendPlayTime,
desk.totalWarTime,
ServerConfigManager.Instance.GameId.ToString()
));
}
}
if (desk.deskinfo.creatStyle == 5)
{
// 公会游玩局数
var clubIds = desk.Select(x => x.ClubId).Distinct();
foreach (var clubId in clubIds)
{
eLogs.Add(StatisticsTrackingLogData.Create(
clubId.ToString(),
EventTrackConst.GameClubPlayCount,
1,
ServerConfigManager.Instance.GameId.ToString()
));
}
}
// 解散原因
eLogs.Add(StatisticsTrackingLogData.Create(
ServerConfigManager.Instance.GameId.ToString(),
EventTrackConst.GameDisCount,
1,
style.ToString()
));
EventTrackingUtil.OnEvent(eLogs);
}
desk.DisBank(style);
DeskInfo deskinfo = desk.deskinfo;
//只要是解散,都应该要算输赢分
Room.SetSumBurs(deskinfo);
SetPlayerScoreRecord(deskinfo);
deskinfo.isClose = 1;
//先发包
desk.SendFriendRoomOver(style);
//Debug.Info($"解散原因:{deskinfo.GetDisBankMemo(style)}");
//修改玩家数据,修改桌子数据 --执行完玩家就离线了!
desk.DisBankAfter(style);
//修改链表数据
//添加到闲置的桌子!
ting.AddIdleing(desk);
if (deskinfo.creatStyle == 5)
{
WayManager.instance.WayDeskChangeSend(deskinfo.creatUserid, deskinfo.wayid, deskinfo.weiyima, 1);
}
int rm = 0;
if (!int.TryParse(desk.deskinfo.roomNum, out rm))
{
Debug.Error("房间号竟然不是数字!");
return;
}
Debug.Info("获取到房间号:" + rm);
int idx = rm % 10;
if (!allDesks[idx].Remove(rm))
{
Debug.Error("alldesk中竟然没有此房间!");
return;
}
}
/// <summary>
/// 根据房间号查找桌子
/// </summary>
/// <returns></returns>
public Desk FindDesk(int deskNum)
{
if (ting == null)
return null;
if (deskNum < 0)
return null;
int idx = deskNum % 10;
Desk desk = null;
if (allDesks[idx].TryGetValue(deskNum, out desk))
return desk;
return null;
}
/// <summary>
/// 请求解散房间包
/// </summary>
/// <param name="pl"></param>
private void placeDisBank(PlayerDataAsyc pl)
{
if (pl.friendRoomNum <= 0)
{
Debug.Error("此玩家没有朋友房!");
return;
}
Desk dsk = FindDesk(pl.friendRoomNum);
if (dsk == null)
{
Debug.Error("逻辑错误,没找到这个桌子" + pl.friendRoomNum);
return;
}
if (dsk.deskinfo.noWar)
{
Debug.Error("未开战不处理!");
return;
}
if (dsk.deskinfo.isDising)
{
Debug.Warning("正在处理解散房间!");
return;
}
if (dsk.deskinfo.rule.RuleEx != null && dsk.deskinfo.rule.RuleEx.CanRequestDissolveCnt < 0)
{
Debug.Log("不支持解散!");
return;
}
if (dsk.deskinfo.rule.RuleEx != null && dsk.deskinfo.rule.RuleEx.CanRequestDissolveCnt > 0 &&
dsk.deskinfo.RequestDissolveCnt >= dsk.deskinfo.rule.RuleEx.CanRequestDissolveCnt)
{
Debug.Log("请求解散的次数达到上限!");
return;
}
dsk.deskinfo.isDising = true;
dsk.deskinfo.DisCount = DeskInfo.DisTimeOut;
dsk.deskinfo.RequestDissolveCnt++;
int len = dsk.deskinfo.plsDis.Length;
DisReponse(pl, true, true);
}
/// <summary>
/// 请求立即开战
/// </summary>
/// <param name="pack"></param>
public void placeOnceFight(GamePack pack)
{
Debug.Info("得到立即开战包:");
placeOnceFight(pack.pl, pack.Head);
}
/// <summary>
/// 请求开战
/// </summary>
/// <param name="pl">玩家数据</param>
/// <param name="head">包头</param>
private void placeOnceFight(PlayerDataAsyc pl, PackHead head)
{
if (ting == null)
return;
if (pl.friendRoomNum <= 0)
{
Debug.Error("玩家没有朋友房!");
return;
}
Desk dsk = FindDesk(pl.friendRoomNum);
if (dsk == null)
{
Debug.Error("逻辑错误,没找到这个桌子" + pl.friendRoomNum);
return;
}
if (dsk.deskinfo.rule.minCnt >= dsk.deskinfo.rule.maxCnt)
{
Debug.Error("没有设置立即开战!");
return;
}
if (!dsk.deskinfo.noWar)
{
Debug.Error("开战了不处理!");
return;
}
if (head.otherInt == null || head.otherInt.Length < 1)
return;
dsk.deskinfo.OnceFight[dsk.deskinfo.seat[pl.seat]] = head.otherInt[0];
dsk.SendOnceFight();
}
/// <summary>
/// 解散回复包
/// </summary>
/// <param name="pl">回复的玩家</param>
/// <param name="Dis">是否同意解散</param>
/// <param name="source">是否是发起者</param>
public void DisReponse(PlayerDataAsyc pl, bool Dis, bool source)
{
if (pl.friendRoomNum <= 0)
return;
Desk dsk = FindDesk(pl.friendRoomNum);
if (!dsk.deskinfo.isDising)
return;
int len = dsk.deskinfo.plsDis.Length;
for (int i = 0; i < len; i++)
{
//这个位置有人 没投票过 是这个玩家
if (dsk.deskinfo.pls[i] != null && dsk.deskinfo.plsDis[i] == 0 &&
dsk.deskinfo.pls[i].userid == pl.userid)
{
if (Dis)
{
if (source)
{
dsk.deskinfo.DisUserId = pl.userid;
}
dsk.deskinfo.plsDis[i] = 1;
dsk.SendDisInfo(source ? 1 : 2, pl.userid, pl.nickname);
}
else
{
dsk.deskinfo.DisUserId = 0;
//拒绝解散
//dsk.deskinfo.plsDis[i] = -1;
dsk.deskinfo.isDising = false;
dsk.SendDisInfo(3, pl.userid, pl.nickname);
for (int j = 0; j < len; j++)
{
dsk.deskinfo.plsDis[j] = 0;
}
Debug.Log("告诉玩家,谁谁谁拒绝解散!");
return;
}
break;
}
}
//检查是否全部人都同意解散
bool isDis = true;
for (int i = 0; i < len; i++)
{
if (dsk.deskinfo.pls[i] != null)
{
//这个位置有人且不是同意
if (dsk.deskinfo.plsDis[i] != 1)
{
isDis = false;
break;
}
}
}
if (isDis)
{
//解散房间
Debug.Info("所有人同意解散!");
DisBank(dsk,2);
}
}
public void DeductCard(PlayerDataAsyc pl, DeskInfo info)
{
if (info.fangka == 0)
{
return;
}
if (info.creatStyle == 5)
{
//通知竞技比赛扣除竞技比赛房卡
ClubDataChange cdc = new ClubDataChange()
{
style = 1,
clubid = info.creatUserid,
value = -info.fangka
};
// PackHead head = PackHead.Create(ServerPackAgreement.ClubDataChange);
// ClubDataManager.AddClubCardAsyn(info.creatUserid, -info.fangka);
// GlobalMQ.instance.DeliveryEveryOne((int)ModuleType.ClubModule, GlobalMQ.CreateMessage(head, cdc), true,
// true);
// head.Dispose();
// 埋点
EventTrackingUtil.OnEvent(StatisticsTrackingLogData.Create(
info.creatUserid.ToString(),
EventTrackConst.GamePlayCardCount,
info.fangka,
ServerConfigManager.Instance.GameId.ToString()
));
}
else
{
if (pl == null)
{
return;
}
//通知数据中心,扣除玩家的房卡
if (info.fangka != 0)
{
PlayerDataChange pdc = PlayerDataChange.Create(info.creatUserid);
pdc.fangkaChange = -info.fangka;
PlayerFun.WritePlayerDataAsync(pdc);
pl.fangka -= info.fangka;
}
}
GameManager.instance.DelFangKa += info.fangka;
}
/// <summary>
/// 创建桌子--这种是新创建的
/// </summary>
/// <param name="pl">创建者</param>
/// <param name="info">桌子信息</param>
/// <returns></returns>
public int CreateDesk(PlayerDataAsyc pl, DeskInfo info, ref string errinfo, ref int errcode)
{
//DeductCard(pl, info);
Debug.Info("创建所需的房卡数值:" + info.fangka);
Desk desk = ting.GetDesk(DeskState.Idle, info);
desk.Init();
Debug.Info("创建桌子实例!" + info.creatStyle + "," + info.creatUserid + "," + desk.id);
int deskNum = int.Parse(info.roomNum);
AddDesk(deskNum, desk);
Debug.Info("获取到房间号:" + deskNum);
ting.RemoveIdle(desk);
ting.AddQueueing(desk);
if (EnterDesk(deskNum, pl, info.rule.pwd, info.creatStyle == 5, ref errinfo, ref errcode) == 1)
{
Debug.Info("玩家进入房间成功! cccdd:" + pl.ClubId);
}
else
{
Debug.Error("自己创建的房间怎么还有进不去的情况?????" + info.roomNum + "," + errinfo);
return 0;
}
//Debug.Log("创建成功!");
Debug.Log(info.ToString());
return 1;
}
/// <summary>
/// 添加desk
/// </summary>
/// <param name="deskNum"></param>
/// <param name="desk"></param>
protected void AddDesk(int deskNum, Desk desk)
{
if (ting == null)
{
Debug.Error("非朋友房不得使用!");
return;
}
int idx = deskNum % 10;
Debug.Info("添加房间...." + deskNum);
allDesks[idx].Add(deskNum, desk);
}
/// <summary>
/// 处理玩家解散房间包
/// </summary>
/// <param name="pl"></param>
public void DisBank(PlayerDataAsyc pl)
{
//先判断
if (pl.outline == 1)
{
Debug.Error("玩家离线哪里来的包!");
return;
}
if (pl.friendRoomNum <= 0)
{
Debug.Error("玩家没有房间号!");
return;
}
if (pl.state == (int)PlayerState.Desk || pl.state == (int)PlayerState.Ready)
{
if (!ting.isExists(pl.deskid))
{
Debug.Error("解散桌子错误!没有这个桌子!");
return;
}
var desk = ting[pl.deskid];
if (desk.CheckDisbank(pl))
{
Debug.Info("解散房间的收包!");
DisBank(desk, 5);
}
else
{
Debug.Warning("解散失败!");
}
}
else
{
Debug.Warning("玩家状态不符合解散桌子!");
return;
}
}
/// <summary>
/// 本来就有的桌子
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
public void LoadDesk(DeskInfo info)
{
Desk desk = ting.GetDesk(DeskState.Idle, info);
desk.Init();
desk.LoadDesk();
AddDesk(int.Parse(info.roomNum), desk);
ting.RemoveIdle(desk);
if (desk.deskinfo.nowCnt == 0)
{
//0表示未开战 不等于0表示开战
ting.AddQueueing(desk);
}
else
{
desk.waitRecover = true;
ting.AddWaring(desk);
}
}
/// <summary>
/// 删除玩法
/// </summary>
public void DelWay(int clubid, string wayid)
{
//思路 把这个玩法的所有桌子的唯一码拿到手。
//获取到桌子信息, 判断桌子是否已经开战,如果没有开战则解散桌子
var weiyimaArray = WayManager.instance.GetDesksWeiYiMa(clubid, wayid).Select(p => (string)p.Name)
.ToArray(); //用这个得到唯一码
foreach (var weiyima in weiyimaArray)
{
if (!string.IsNullOrEmpty(weiyima))
{
var roomNum = Room.GetRoomNum(weiyima); //Room.GetRoomNum 传递唯一码获取房间号
if (int.TryParse(roomNum, out var roomnum))
{
var weiyimaOrig = string.Empty;
ServerNode node = null; //再根据房间号获取到唯一码 与 node. 返回值表示是否有这个房间。如果没这个房间输出错误信息。
if (Room.GetWeiyima(roomnum, ref weiyimaOrig, ref node))
{
//这个唯一码要与 刚才得到的唯一码进行对比,验证是否是同一个桌子 。 房间号是可以重复的, 桌子的唯一码却不会重复。
if (weiyima.Equals(weiyimaOrig))
{
//验证成功的话FindDesk 查找到桌子
var desk = FindDesk(roomnum);
//桌子是空输出错误信息
if (desk == null)
{
Debug.Error(
$"DelWay desk is null! clubid: {clubid}, wayid: {wayid}, weiyima: {weiyima}, roomNum: {roomNum}.");
}
else if (!desk.isWar)
{
//再判断桌子是否已经开战 isWar 属性。
DisBank(desk, 6); //已经开战不处理,未开战调用 DisBank() 调用解散桌子
}
}
}
}
}
}
}
/*
* redis中的数据解构
*
* friendroom.lastRoomNum hash类型 lastDateTime 上次创建的时间 lastDateRoomNum 上次创建房间的房间号
* friendroom.room.num string类型 房间号表 -> 存储唯一吗值
* friendroom.唯一码 -> 房间数据
* friendroom.唯一码_playerdata_idx -> 存储房间的玩家数据
* friendroom.唯一码_score_idx -> 存储房间分数
*
* */
/*
*
* 朋友房唯一码 = 日期+时间+毫秒+房间号
*
{创建房间的算法}
{
1.房间号的算法{ --混淆游戏的火爆程度
变量 房间增量 当前检测房间号
1.房间增量 = 上次创建房间与当前时间的时间差 / 10 % 1000
2.当前检测的房间号 = (上次创建房间的房间号+房间增量) % 1000000
3.对比是否与上次创建的房间号一样,房间号+1
}
2.检测房间可用 传入检查的房间号 检查次数{
拿到房间号->去检查
检查次数+1;
如果检查房间号发现已经检查 100 次 返回未检查到可用房间->发包玩家重试
第一种情况2.1 房间号表有值
{
根据房间的唯一码去获取朋友房数据
{
1.房间已经超时 应该解散(未开战,过了半个小时->执行解散(发送解散命令) 开战了->过了24小时未战斗完(解散))
去执行解散房间
检查的房间号+1 -> 继续调用检测房间方法
2.房间正常
检查的房间号+1 -> 继续调用检测房间方法
}
第二种情况2.2 房间号表中没值
{
执行创建房间;
}
}
3.创建房间->检测次数
分布式加锁
再做检查,已防万一已被别的程序创建!
3.1检查发现不可用 返回创建失败->执行检查房间号,检测次数+1
cha
3.2检查可用
1. 根据房间数据创建桌子,生成房间数据
2. 根据房间数据,保存到房间分数表、房间玩家数据表,房间数据表,房间唯一吗表,上次创建房间的房间号表
分布式解锁
4.解散房间
判断房间号是否是自己模块管理的
1.不是本模块管理,发包给管理的模块处理 ->有可能模块不在线,(或者不开了.....手动清楚数据,一般不应该出现这种情况)
2.是本模块管理{
清楚桌子内存数据,
分布式 加锁
1.删除房间号表中的值,
分布式 借锁
2.redis桌子数据异步存储到sql.存储完成后删除redis中的桌子数据
}
}
*/
/// <summary>
/// 快速加入
/// </summary>
public class JoinWanFa
{
/// <summary>
/// 包头
/// </summary>
public readonly PackHead head;
/// <summary>
/// 加入房间
/// </summary>
public readonly JoinFriendRoom jfr;
/// <summary>
/// 加入玩法
/// </summary>
/// <param name="head"></param>
/// <param name="jfr"></param>
public JoinWanFa(PackHead head, JoinFriendRoom jfr)
{
this.head = head;
this.jfr = jfr;
}
/// <summary>
/// 获取本次要计算的房间唯一码值
/// </summary>
/// <param name="jfr"></param>
/// <param name="rooms"></param>
protected void GetRoomWeiYiMa(JoinFriendRoom jfr, HashEntry[] rooms)
{
bool isLast = jfr.lastjoinweiyima == null;
foreach (var item in rooms)
{
if (!isLast)
{
//还没找到上次计算的房间
isLast = item.Name == jfr.lastjoinweiyima;
} //else { //找到了,找本次要运算的房间 2020-06-17 号修改,这个应该写错了,会跳过第一个房间
int cnt = 0;
if (!item.Value.TryParse(out cnt))
{
Debug.Fatal("存储的值错误,怎么存储的值非整数类型!" + jfr.way.weiyima + "," + jfr.way.Clubid);
continue;
}
if (isLast && cnt < jfr.way.dskrule.maxCnt)
{
//房间没满人
jfr.joinweiyima = item.Name; //选定要运算的房间
break;
}
//}
}
}
/// <summary>
/// 开始房间
/// </summary>
/// <returns></returns>
public async Task Start(PackHead head)
{
if (jfr == null)
{
Debug.Error("936983A9-02C9-4B81-A7F4-C06C7385B06B:");
return;
}
if (jfr.deviceInfo == null)
{
Debug.Error("加入玩法时设备信息为空!!!");
GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.ClubJoinDeskNotDeviceInfo);
return;
}
if (head.ip == null)
{
Debug.Error("玩家的ip 是 空!!!");
GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.ClubJoinDeskNotIp);
return;
}
int userid = head.userid;
if (DoingUserIds.Contains(userid))
{
Debug.Error($"正在处理别的事务:{head.userid}");
GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.ClubJoinDeskDoing);
return;
}
Debug.Info("进入玩法!");
HashEntry[] rooms = null;
try
{
DoingUserIds.Add(userid);
//如果当前进入房间有值,尝试进入房间
//如果当前进入房间没值,尝试计算当前要进入的房间
if (jfr.joinweiyima == null)
{
//没有想进入的房间,说明是从竞技比赛过来的
if (string.IsNullOrEmpty(jfr.way.weiyima))
{
Debug.Error("玩法的唯一码竟是空值!!!!");
GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.ClubJoinDeskParamError);
return;
}
//去找一个房间
rooms = WayManager.instance.GetDesksWeiYiMa(jfr.way.Clubid, jfr.way.weiyima);
Debug.Info("找到所有的房间:" + jfr.way.Clubid + "," + jfr.way.weiyima);
GetRoomWeiYiMa(jfr, rooms);
}
if (jfr.joinweiyima != null)
{
//有则尝试加入房间!
//先把房间找到->
string strRoomNum = Room.GetRoomNum(jfr.joinweiyima);
Debug.Info("找到房间:" + strRoomNum + "," + jfr.joinweiyima);
//管理该房间的节点
ServerNode node = null;
string weiyima = null;
//拿到房间号,先看本地有没有,没有的话则加载起来
int roomnum = 0;
if (int.TryParse(strRoomNum, out roomnum))
{
//有房间号
if (Room.GetWeiyima(roomnum, ref weiyima, ref node))
{
//拿到唯一码
if (weiyima == jfr.joinweiyima)
{
//唯一码一致
if (!GameBase.instance.myUtil.Equals(node))
{
//交给管理模块处理
GlobalMQ.instance.DeliveryOne(node, GlobalMQ.CreateMessage(head, jfr), true);
}
else
{
//本模块处理
//没在本地加载到本地
Debug.Info("本地处理");
DoJoinFriendRoom djfr = new DoJoinFriendRoom(head,
new JoinRoom(roomnum.ToString(), weiyima) { deviceinfo = jfr.deviceInfo },
jfr, false, true);
djfr.IsTestPack = jfr.IsTestPack;
await djfr.Start();
if (!djfr.result)
{
//进入失败 再来一次
Debug.Warning("进入失败,去创建一个房间!");
jfr.lastjoinweiyima = weiyima;
jfr.joinweiyima = null;
var crp1 = new CreateRoomPack()
{
deviceInfo = jfr.deviceInfo, isAuto = jfr.isAuto, ClubId = jfr.ClubId,
Score = jfr.Score,
TaskId = jfr.TaskId,
IsTestPack = jfr.IsTestPack,
deskinfo = new DeskInfo()
{
wayid = jfr.way.weiyima, creatStyle = 5,
creatUserid = jfr.way.Clubid,
rule = jfr.way.dskrule
}
};
if (instance.GetFriendRoomNum(head, crp1))
{
await instance.CreatRoomLogin(head, crp1, true, false);
}
/*
head.otherString = new string[] { djfr.errinfo};
head.packlx = ServerPackAgreement.TransFerHttp;
head.transfer = GameSeverAgreement.notJoinFriendRoom; */
/*
head.packlx = GlobalManager.instance.myUtil.id * 10000 + head.packlx;
GlobalMQ.instance.DeliveryOne(node, GlobalMQ.CreateMessage(head, jfr), true);
Debug.Warning("进入失败,发包再试!" + head.ip);*/
}
else
{
if (jfr.TaskId > 0)
{
GeneralSendPack.SendJoinDeskResult(jfr.TaskId, MessageErrCode.Success);
}
else
{
Debug.Info("把玩家拉入桌子!!!");
//把玩家拉入桌子
head.transfer = ServerPackAgreement.ReConnection;
head.packlx = ServerPackAgreement.TransFerHttp;
head.otherInt = new int[] { ServerConfigManager.Instance.ClientId };
GlobalMQ.instance.DeliveryOne(head.GetUtil(),
GlobalMQ.CreateMessage(head, null), true);
}
}
}
return;
}
}
}
}
DeskInfo dskinfo = new DeskInfo();
dskinfo.wayid = jfr.way.weiyima;
dskinfo.creatStyle = 5;
dskinfo.creatUserid = jfr.way.Clubid;
dskinfo.rule = jfr.way.dskrule;
if (dskinfo.rule.RuleEx == null)
dskinfo.rule.RuleEx = new DeskRuleEx();
dskinfo.rule.RuleEx.ReadyTimeout = jfr.ReadyTimeOut;
Debug.Info("去创建朋友房!" + dskinfo.wayid);
CreateRoomPack crp = new CreateRoomPack();
crp.deskinfo = dskinfo;
crp.deviceInfo = jfr.deviceInfo;
crp.isAuto = jfr.isAuto;
crp.ClubId = jfr.ClubId;
crp.Score = jfr.Score;
crp.TaskId = jfr.TaskId;
crp.IsTestPack = jfr.IsTestPack;
//获取到房间号,去创建房间
if (instance.GetFriendRoomNum(head, crp))
{
await instance.CreatRoomLogin(head, crp, true, false);
}
//(head, crp);
}
catch (Exception e)
{
Debug.Error($"报错:{e.Message} {e.StackTrace}");
}
finally
{
DoingUserIds.Remove(userid);
}
}
}
}
}