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
718 lines
22 KiB
C#
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,
|
|
}
|
|
}
|
|
} |