Files
hjha-server/GameModule/Manager/LuckPlayerManager.Club.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

718 lines
22 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using GameDAL.FriendRoom;
using MrWu.Debug;
using Newtonsoft.Json;
namespace Server
{
// 配置倍率 平衡区间 比如 20 倍的 平衡参数 7500
// 2 倍 平衡参数 1000
//
// 根据倍率 配置那些人需要平衡
public partial class LuckPlayerManager
{
private BalanceData _balanceData = new BalanceData();
/// <summary>
/// 所有的平衡配置
/// </summary>
private List<BalanceRange> BalanceAllConfigs => _balanceData.BalanceRanges;
private Dictionary<float, BalanceRange> BalanceRangesDic = new Dictionary<float, BalanceRange>();
/// <summary>
/// 初始化,添加,删除 才需修改
/// </summary>
private Dictionary<float, BalanceRoomRateRule> RulesDic = new Dictionary<float, BalanceRoomRateRule>();
private const string BalanceDataPath = "LuckRecord/ClubBalanceData.txt";
public float GetBalanceRangeId(float beilv, int fightCnt)
{
return fightCnt * 10000 + beilv;
}
/// <summary>
/// 获取所有的配置
/// </summary>
/// <returns></returns>
public IEnumerable<BalanceRange> GetAllBalanceRange()
{
return BalanceAllConfigs;
}
/// <summary>
/// 添加平衡区间
/// </summary>
/// <param name="beilv">倍率</param>
/// <param name="fightCnt">总局数</param>
/// <param name="balanceValue">平衡值</param>
/// <returns></returns>
public bool AddBalanceRange(float beilv, int fightCnt, int balanceValue)
{
BalanceRange balanceRange = GetBalanceRange(beilv, fightCnt);
if (balanceRange == null)
{
balanceRange = new BalanceRange()
{
BeiLv = beilv,
MaxFightCnt = fightCnt,
BalanceValue = balanceValue
};
BalanceAllConfigs.Add(balanceRange);
//添加所有玩家
for (int i = 0; i < _balanceData.UserIds.Count; i++)
{
AddBalancePlayer(balanceRange, _balanceData.UserIds[i]);
}
return true;
}
return false;
}
public bool SetBalanceRange(float beilv, int fightCnt, int balanceValue)
{
if (balanceValue < 1000)
{
Debug.Error("平衡参数过低!");
return false;
}
BalanceRange balanceRange = GetBalanceRange(beilv, fightCnt);
if (balanceRange != null)
{
balanceRange.BalanceValue = balanceValue;
return true;
}
return false;
}
/// <summary>
/// 移除平衡区间
/// </summary>
/// <param name="beilv"></param>
/// <param name="fightCnt"></param>
/// <returns></returns>
public bool RemoveBalanceRange(float beilv, int fightCnt)
{
BalanceRange balanceRange = GetBalanceRange(beilv, fightCnt);
if (balanceRange == null)
{
return false;
}
BalanceRangesDic.Remove(balanceRange.Id);
BalanceAllConfigs.Remove(balanceRange);
return true;
}
public BalanceRange GetBalanceRange(float id)
{
if (!BalanceRangesDic.TryGetValue(id, out BalanceRange balanceRange))
{
for (int i = 0; i < BalanceAllConfigs.Count; i++)
{
if (Math.Abs(BalanceAllConfigs[i].Id - id) < 0.001f)
{
balanceRange = BalanceAllConfigs[i];
BalanceRangesDic[id] = balanceRange;
}
}
}
return balanceRange;
}
public BalanceRange GetBalanceRange(float beiLv, int fightCnt)
{
return GetBalanceRange(GetBalanceRangeId(beiLv, fightCnt));
}
public bool AddRoomRateRule(float beiLv, int fightCnt, int modeType)
{
BalanceRoomRateRule rule = GetRoomRateRule(beiLv, fightCnt);
if (rule != null)
{
return false;
}
rule = new BalanceRoomRateRule()
{
ModeType = modeType,
BeiLv = beiLv,
FightCnt = fightCnt
};
RulesDic[GetBalanceRangeId(beiLv, fightCnt)] = rule;
_balanceData.Rules.Add(rule);
return true;
}
public bool RemoveRoomRateRule(float beiLv, int fightCnt)
{
BalanceRoomRateRule rule = GetRoomRateRule(beiLv, fightCnt);
if (rule == null)
{
return false;
}
bool result = _balanceData.Rules.Remove(rule);
if (result && !RulesDic.Remove(GetBalanceRangeId(beiLv, fightCnt)))
{
Debug.Error("未能删除规则");
return false;
}
return result;
}
public bool AddRoomRateRuleItem(float beiLv, int fightCnt, int minScore, int maxScore, int roomRate)
{
BalanceRoomRateRule rule = GetRoomRateRule(beiLv, fightCnt);
if (rule == null)
{
return false;
}
if (maxScore <= minScore || roomRate <= 0)
{
return false;
}
for (int i = 0; i < rule.Ranges.Count; i++)
{
if (maxScore <= rule.Ranges[i].MinScore || minScore > rule.Ranges[i].MaxScore)
{
continue;
}
Debug.Error("区间有交叉!");
return false;
}
rule.Ranges.Add(new BalanceRoomRange()
{
MinScore = minScore,
MaxScore = maxScore,
Rate = roomRate
});
return true;
}
public bool RemoveRoomRateRuleItem(float beiLv, int fightCnt, int minScore, int maxScore, int roomRate)
{
BalanceRoomRateRule rule = GetRoomRateRule(beiLv, fightCnt);
if (rule == null)
{
return false;
}
for (int i = 0; i < rule.Ranges.Count; i++)
{
if (rule.Ranges[i].MinScore == minScore && rule.Ranges[i].MaxScore == maxScore &&
roomRate == rule.Ranges[i].Rate)
{
rule.Ranges.RemoveAt(i);
return true;
}
}
return false;
}
public BalanceRoomRateRule GetRoomRateRule(float beiLv, int fightCnt)
{
if (RulesDic.TryGetValue(GetBalanceRangeId(beiLv, fightCnt), out BalanceRoomRateRule roomRateRule))
{
return roomRateRule;
}
return null;
}
public List<Tuple<BalanceRange, BalancePlayer>> GetBalancePlayers(int userid)
{
List<Tuple<BalanceRange, BalancePlayer>> balancePlayers = new List<Tuple<BalanceRange, BalancePlayer>>();
for (int i = 0; i < BalanceAllConfigs.Count; i++)
{
BalancePlayer player = GetBalancePlayer(BalanceAllConfigs[i], userid);
if (player == null)
{
break;
}
balancePlayers.Add(new Tuple<BalanceRange, BalancePlayer>(BalanceAllConfigs[i], player));
}
return balancePlayers;
}
public BalancePlayer GetBalancePlayer(BalanceRange balanceRange, int userid)
{
if (balanceRange.BalancePlayersDic.TryGetValue(userid, out BalancePlayer player))
{
return player;
}
return null;
}
public bool AddBalancePlayer(int userid)
{
if (ExistsPlayer(userid))
{
return false;
}
_balanceData.UserIds.Add(userid);
//为每个玩法都添加上
for (int i = 0; i < BalanceAllConfigs.Count; i++)
{
AddBalancePlayer(BalanceAllConfigs[i], userid);
}
return true;
}
public bool RemoveBalancePlayer(int userid)
{
if (_balanceData.UserIds.Remove(userid))
{
for (int i = 0; i < BalanceAllConfigs.Count; i++)
{
RemoveBalancePlayer(BalanceAllConfigs[i], userid);
}
return true;
}
return false;
}
private void AddBalancePlayer(BalanceRange balanceRange, int userid)
{
balanceRange.BalancePlayersDic.TryAdd(userid, new BalancePlayer()
{
UserId = userid
});
}
private void RemoveBalancePlayer(BalanceRange balanceRange, int userid)
{
if (balanceRange.BalancePlayersDic.TryRemove(userid, out BalancePlayer _balance))
{
Debug.Info($"移除用户:{_balance.Score}");
}
}
public bool ExistsPlayer(int userid)
{
for (int i = 0; i < _balanceData.UserIds.Count; i++)
{
if (_balanceData.UserIds[i] == userid)
{
return true;
}
}
return false;
}
public List<string> FindBalancePlayer(int userid)
{
List<string> logs = new List<string>();
for (int i = 0; i < BalanceAllConfigs.Count; i++)
{
BalancePlayer banBalancePlayer = GetBalancePlayer(BalanceAllConfigs[i], userid);
if (banBalancePlayer == null)
{
continue;
}
logs.Add(
$"倍率:{BalanceAllConfigs[i].BeiLv} 总局数:{BalanceAllConfigs[i].MaxFightCnt} {banBalancePlayer.ToString()}");
}
return logs;
}
/// <summary>
/// 加载俱乐部平衡数据
/// </summary>
private void LoadClubBalanceData()
{
if (!File.Exists(BalanceDataPath))
{
return;
}
string jsondata = File.ReadAllText(BalanceDataPath);
_balanceData = JsonConvert.DeserializeObject<BalanceData>(jsondata);
for (int i = 0; i < BalanceAllConfigs.Count; i++)
{
foreach (var balancePlayer in BalanceAllConfigs[i].BalancePlayers)
{
BalanceAllConfigs[i].BalancePlayersDic[balancePlayer.UserId] = balancePlayer;
}
}
if (_balanceData.Rules != null)
{
for (int i = 0; i < _balanceData.Rules.Count; i++)
{
RulesDic[_balanceData.Rules[i].Id] = _balanceData.Rules[i];
}
}
}
private void SaveClubBalanceData()
{
if (BalanceAllConfigs.Count <= 0)
{
return;
}
FileInfo fileInfo = new FileInfo(BalanceDataPath);
if (!fileInfo.Directory.Exists)
{
fileInfo.Directory.Create();
}
for (int i = 0; i < BalanceAllConfigs.Count; i++)
{
BalanceAllConfigs[i].BalancePlayers.Clear();
BalanceAllConfigs[i].BalancePlayers.AddRange(BalanceAllConfigs[i].BalancePlayersDic.Values);
}
File.WriteAllText(BalanceDataPath, JsonConvert.SerializeObject(_balanceData));
}
public bool SetSessionFightScore(float beilv, int fightCnt, int userid, int score)
{
BalanceRange balanceRange = GetBalanceRange(beilv, fightCnt);
if (balanceRange == null)
{
return false;
}
BalancePlayer balancePlayer = GetBalancePlayer(balanceRange, userid);
if (balancePlayer == null)
{
return false;
}
balancePlayer.Score += score;
return true;
}
/// <summary>
/// 添加一场战斗的分
/// </summary>
/// <param name="beilv"></param>
/// <param name="userid"></param>
/// <param name="score"></param>
/// <param name="isBigWinner">是否是大赢家</param>
public void AddSessionFightScore(float beilv, int fightCnt, int userid, int score, bool isBigWinner)
{
BalanceRange balanceRange = GetBalanceRange(beilv, fightCnt);
if (balanceRange == null)
{
return;
}
BalancePlayer balancePlayer = GetBalancePlayer(balanceRange, userid);
if (balancePlayer == null)
{
return;
}
Debug.Info($"AddSessionFightScore: {userid} {score}");
//先得到规则
BalanceRoomRateRule rule = GetRoomRateRule(beilv, fightCnt);
if (rule != null) //处理房费
{
//得到区间
BalanceRoomRange range = null;
for (int i = 0; i < rule.Ranges.Count; i++)
{
if (score > rule.Ranges[i].MinScore && score <= rule.Ranges[i].MaxScore)
{
range = rule.Ranges[i];
break;
}
}
if (range != null)
{
if (rule.ModeType == 1 || (rule.ModeType == 2 && isBigWinner))
{
score -= range.Rate;
balancePlayer.RoomRate += range.Rate;
Debug.Info($"扣除房费:{balancePlayer.RoomRate}");
}
}
}
balancePlayer.Score += score;
balancePlayer.TempScore = 0;
}
/// <summary>
/// 添加一局战斗的分 子
/// </summary>
/// <param name="beilv"></param>
/// <param name="userid"></param>
/// <param name="score"></param>
public void AddOnceFightScore(float beilv, int fightCnt, int userid, int score)
{
BalanceRange balanceRange = GetBalanceRange(beilv, fightCnt);
if (balanceRange == null)
{
Debug.Info($"没找到玩法! {beilv} {fightCnt}");
return;
}
BalancePlayer balancePlayer = GetBalancePlayer(balanceRange, userid);
if (balancePlayer == null)
{
Debug.Info($"没找到玩法 玩家:{userid}!");
return;
}
Debug.Info($"AddOnceFightScore : {userid} {(score * beilv)}");
balancePlayer.TempScore += (int)(score * beilv);
}
/// <summary>
/// 获取平衡数据
/// </summary>
/// <param name="beilv"></param>
/// <param name="userid"></param>
/// <returns></returns>
public ClubPlayerBalanceType GetBalancePlayerType(float beilv, int fightCnt, int userid)
{
BalanceRange balanceRange = GetBalanceRange(beilv, fightCnt);
if (balanceRange == null)
{
return ClubPlayerBalanceType.None;
}
BalancePlayer balancePlayer = GetBalancePlayer(balanceRange, userid);
if (balancePlayer == null)
{
return ClubPlayerBalanceType.None;
}
int score = balancePlayer.TempScore + balancePlayer.Score;
int diffValue = Math.Abs(score) - balanceRange.BalanceValue;
if (diffValue <= 0)
{
Debug.Info($"已经是平衡状态! {userid}");
return ClubPlayerBalanceType.Normal;
}
float rate = (diffValue / (float)balanceRange.BalanceValue) * 0.5f;
if (score < 0) //输了就加大发牌概率
{
rate *= 2f;
}
Debug.Info($"计算概率:{userid} {diffValue} {balancePlayer.Score} {rate}");
Random random = GetRandom();
bool isBalance = random.NextDouble() < rate;
ReleaseRandom(random);
if (isBalance)
{
return score > 0 ? ClubPlayerBalanceType.BadLuck : ClubPlayerBalanceType.Luck;
}
return ClubPlayerBalanceType.Normal;
}
public class BalanceData
{
/// <summary>
/// 房费规则
/// </summary>
public List<BalanceRoomRateRule> Rules = new List<BalanceRoomRateRule>();
/// <summary>
/// 玩法配置
/// </summary>
public List<BalanceRange> BalanceRanges = new List<BalanceRange>();
/// <summary>
/// 所有玩家
/// </summary>
public List<int> UserIds = new List<int>();
}
/// <summary>
/// 房费规则
/// </summary>
public class BalanceRoomRateRule
{
/// <summary>
/// 这个用来做ID
/// </summary>
[JsonIgnore]
public float Id
{
get { return FightCnt * 10000 + BeiLv; }
}
/// <summary>
/// 模式类型 1 所有人出 2 大赢家出
/// </summary>
public int ModeType;
/// <summary>
/// 房费
/// </summary>
public float BeiLv;
/// <summary>
/// 总局数
/// </summary>
public int FightCnt;
/// <summary>
/// 区间
/// </summary>
public List<BalanceRoomRange> Ranges = new List<BalanceRoomRange>();
}
/// <summary>
/// 房费区间
/// </summary>
public class BalanceRoomRange
{
/// <summary>
/// 最小值
/// </summary>
public int MinScore;
/// <summary>
/// 最大值
/// </summary>
public int MaxScore;
/// <summary>
/// 房费
/// </summary>
public int Rate;
}
/// <summary>
/// 平衡区间
/// </summary>
public class BalanceRange
{
/// <summary>
/// 这个用来做ID
/// </summary>
[JsonIgnore]
public float Id
{
get { return MaxFightCnt * 10000 + BeiLv; }
}
/// <summary>
/// 倍率
/// </summary>
public float BeiLv;
/// <summary>
/// 总局数
/// </summary>
public int MaxFightCnt;
/// <summary>
/// 平衡值
/// </summary>
public int BalanceValue;
/// <summary>
/// 平衡玩家的数据
/// </summary>
public List<BalancePlayer> BalancePlayers = new List<BalancePlayer>();
[JsonIgnore]
public ConcurrentDictionary<int, BalancePlayer> BalancePlayersDic =
new ConcurrentDictionary<int, BalancePlayer>();
}
/// <summary>
/// 平衡玩家数据
/// </summary>
public class BalancePlayer
{
/// <summary>
/// 玩家ID
/// </summary>
public int UserId;
/// <summary>
/// 当前分值
/// </summary>
public int Score;
/// <summary>
/// 临时计算用,这个是小局分
/// </summary>
public int TempScore;
/// <summary>
/// 房费
/// </summary>
public int RoomRate;
public override string ToString()
{
return $"Userid:{UserId},Score:{Score},RoomRate:{RoomRate}";
}
}
public enum ClubPlayerBalanceType
{
/// <summary>
/// 不参与平衡
/// </summary>
None = 0,
/// <summary>
/// 正常
/// </summary>
Normal = 1,
/// <summary>
/// 幸运
/// </summary>
Luck = 2,
/// <summary>
/// 不幸运
/// </summary>
BadLuck = 3,
}
}
}