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
304 lines
11 KiB
C#
304 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using GameMessage;
|
|
using MrWu.Debug;
|
|
using Server.Core;
|
|
using Server.DB.Redis;
|
|
using StackExchange.Redis;
|
|
|
|
namespace Server
|
|
{
|
|
public class ActivityPropManager : SingleInstance<ActivityPropManager>
|
|
{
|
|
private readonly Type ActivityPropDataBaseType = typeof(ActivityPropDataInfo);
|
|
|
|
/// <summary>
|
|
/// 道具信息 字典
|
|
/// </summary>
|
|
private readonly Dictionary<ActivityPropType, ActivityPropDataInfo> _activityPropData = new Dictionary<ActivityPropType, ActivityPropDataInfo>();
|
|
|
|
/// <summary>
|
|
/// 所有道具信息
|
|
/// </summary>
|
|
private readonly List<ActivityPropDataInfo> _activityPropDataInfos = new List<ActivityPropDataInfo>();
|
|
|
|
public ActivityPropManager()
|
|
{
|
|
Type[] types = GetType().Assembly.GetTypes();
|
|
foreach (var type in types)
|
|
{
|
|
if (type.IsSubclassOf(ActivityPropDataBaseType))
|
|
{
|
|
ActivityPropDataInfo dataInfo = (ActivityPropDataInfo)Activator.CreateInstance(type);
|
|
_activityPropData[dataInfo.PropType] = dataInfo;
|
|
_activityPropDataInfos.Add(dataInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取道具的过期时间
|
|
/// </summary>
|
|
/// <param name="propType"></param>
|
|
/// <param name="propName"></param>
|
|
/// <returns></returns>
|
|
public DateTime GetExpireTime(ActivityPropType propType,string propName)
|
|
{
|
|
if (!_activityPropData.ContainsKey(propType))
|
|
{
|
|
//没有这个数据,那么现在就过期
|
|
return DateTime.Now;
|
|
}
|
|
|
|
return _activityPropData[propType].GetExpireTime(propName);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取道具数据的KEY
|
|
/// </summary>
|
|
/// <param name="userid"></param>
|
|
/// <param name="propType"></param>
|
|
/// <param name="propName"></param>
|
|
/// <returns></returns>
|
|
private string GetRedisKey(int userid, ActivityPropType propType, string propName)
|
|
{
|
|
return $"ActivityPropData:{userid}:{(int)propType}:{propName}";
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取某个玩家的所有道具数据
|
|
/// </summary>
|
|
/// <param name="userid">玩家的userid</param>
|
|
/// <returns></returns>
|
|
public List<ActivityPropData> GetActivityPropDatas(int userid)
|
|
{
|
|
List<ActivityPropData> datas = new List<ActivityPropData>();
|
|
List<RedisKey> keys = new List<RedisKey>();
|
|
foreach (var activityPropDataInfo in _activityPropDataInfos)
|
|
{
|
|
string[] propNames = activityPropDataInfo.GetPropNames();
|
|
for (int i = 0; i < propNames.Length; i++)
|
|
{
|
|
keys.Add(GetRedisKey(userid, activityPropDataInfo.PropType, propNames[i]));
|
|
datas.Add(new ActivityPropData()
|
|
{
|
|
PropName = propNames[i],
|
|
Id = (int)activityPropDataInfo.PropType,
|
|
});
|
|
}
|
|
}
|
|
|
|
RedisValue[] redisValues = redisManager.db.StringGet(keys.ToArray());
|
|
for (int i = 0; i < redisValues.Length; i++)
|
|
{
|
|
if (!redisValues[i].IsNull && long.TryParse(redisValues[i], out long count))
|
|
{
|
|
datas[i].Count = count;
|
|
}
|
|
}
|
|
|
|
return datas;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取某个道具类型的 数据
|
|
/// </summary>
|
|
/// <param name="userid">谁的</param>
|
|
/// <param name="propType">道具类型</param>
|
|
/// <returns></returns>
|
|
public ActivityPropData[] GetActivityPropDatas(int userid,ActivityPropType propType)
|
|
{
|
|
if (!_activityPropData.ContainsKey(propType))
|
|
{
|
|
Debug.Fatal($"没有这个道具类型:{propType}");
|
|
return null;
|
|
}
|
|
|
|
string[] propNames = _activityPropData[propType].GetPropNames();
|
|
RedisKey[] keys = new RedisKey[propNames.Length];
|
|
for (int i = 0; i < propNames.Length; i++)
|
|
{
|
|
keys[i] = GetRedisKey(userid, propType, propNames[i]);
|
|
}
|
|
|
|
RedisValue[] redisValues = redisManager.db.StringGet(keys);
|
|
ActivityPropData[] datas = new ActivityPropData[redisValues.Length];
|
|
for (int i = 0; i < datas.Length; i++)
|
|
{
|
|
datas[i] = new ActivityPropData();
|
|
datas[i].PropName = propNames[i];
|
|
datas[i].Id = (int)propType;
|
|
if (!redisValues[i].IsNull && long.TryParse(redisValues[i], out long count))
|
|
{
|
|
datas[i].Count = count;
|
|
}
|
|
}
|
|
|
|
return datas;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 获取某种道具的全部数量
|
|
/// </summary>
|
|
/// <param name="userid"></param>
|
|
/// <param name="propType"></param>
|
|
/// <returns></returns>
|
|
public long GetActivityPropCount(int userid, ActivityPropType propType)
|
|
{
|
|
if (!_activityPropData.ContainsKey(propType))
|
|
{
|
|
Debug.Fatal($"没有这个道具类型:{propType}");
|
|
return 0;
|
|
}
|
|
|
|
long result = 0;
|
|
string[] propNames = _activityPropData[propType].GetPropNames();
|
|
RedisKey[] keys = new RedisKey[propNames.Length];
|
|
for (int i = 0; i < propNames.Length; i++)
|
|
{
|
|
keys[i] = GetRedisKey(userid, propType, propNames[i]);
|
|
}
|
|
|
|
RedisValue[] redisValues = redisManager.db.StringGet(keys);
|
|
for (int i = 0; i < redisValues.Length; i++)
|
|
{
|
|
if (!redisValues[i].IsNull && long.TryParse(redisValues[i], out long count))
|
|
{
|
|
result += count;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 添加道具数据
|
|
/// </summary>
|
|
/// <param name="userid"></param>
|
|
/// <param name="propType"></param>
|
|
/// <param name="count"></param>
|
|
public void AddActivityPropData(int userid,ActivityPropType propType,long count)
|
|
{
|
|
if (!_activityPropData.ContainsKey(propType))
|
|
{
|
|
Debug.Fatal($"没有这个道具类型:{userid} {propType} {count}");
|
|
return;
|
|
}
|
|
|
|
if (count <= 0)
|
|
{
|
|
Debug.Error("不能添加小于等于0的道具数据");
|
|
return;
|
|
}
|
|
|
|
string[] propNames = _activityPropData[propType].GetPropNames();
|
|
string nowPropName = propNames[propNames.Length - 1];
|
|
|
|
string key = GetRedisKey(userid, propType, nowPropName);
|
|
TimeSpan ts = _activityPropData[propType].GetExpireTime(nowPropName) - DateTime.Now;
|
|
IBatch batch = redisManager.db.CreateBatch();
|
|
batch.StringIncrementAsync(key, count);
|
|
batch.KeyExpireAsync(key, ts);
|
|
batch.Execute();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 添加道具数据
|
|
/// </summary>
|
|
/// <param name="userid"></param>
|
|
/// <param name="propType"></param>
|
|
/// <param name="propName"></param>
|
|
/// <param name="count"></param>
|
|
public void AddActivityPropData(int userid,ActivityPropType propType,string propName,long count)
|
|
{
|
|
if (!_activityPropData.ContainsKey(propType))
|
|
{
|
|
Debug.Fatal($"没有这个道具类型:{userid} {propType} {count}");
|
|
return;
|
|
}
|
|
|
|
if (count <= 0)
|
|
{
|
|
Debug.Error("不能添加小于等于0的道具数据!");
|
|
return;
|
|
}
|
|
|
|
string key = GetRedisKey(userid, propType, propName);
|
|
TimeSpan ts = _activityPropData[propType].GetExpireTime(propName) - DateTime.Now.AddDays(-1); //延时一天再过期
|
|
IBatch batch = redisManager.db.CreateBatch();
|
|
batch.StringIncrementAsync(key, count);
|
|
batch.KeyExpireAsync(key, ts);
|
|
batch.Execute();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 移除道具数据
|
|
/// </summary>
|
|
/// <param name="userid"></param>
|
|
/// <param name="propType"></param>
|
|
/// <param name="count"></param>
|
|
/// <returns>消耗的道具信息</returns>
|
|
public List<ActivityPropData> DecActivityPropData(int userid, ActivityPropType propType, long count)
|
|
{
|
|
if (!_activityPropData.ContainsKey(propType))
|
|
{
|
|
Debug.Fatal($"没有这个道具类型:{userid} {propType} {count}");
|
|
return null;
|
|
}
|
|
|
|
if (count <= 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
string[] propNames = _activityPropData[propType].GetPropNames();
|
|
RedisKey[] keys = new RedisKey[propNames.Length];
|
|
long[] currentCount = new long[propNames.Length];
|
|
long totalCount = 0;
|
|
for (int i = 0; i < keys.Length; i++)
|
|
{
|
|
keys[i] = GetRedisKey(userid, propType, propNames[i]);
|
|
}
|
|
|
|
RedisValue[] redisValues = redisManager.db.StringGet(keys);
|
|
for (int i = 0; i < redisValues.Length; i++)
|
|
{
|
|
if (!redisValues[i].IsNull && long.TryParse(redisValues[i], out long countValue))
|
|
{
|
|
currentCount[i] = countValue;
|
|
totalCount += countValue;
|
|
}
|
|
}
|
|
|
|
//道具数量不足
|
|
if (totalCount < count)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
List<ActivityPropData> result = new List<ActivityPropData>();
|
|
//剩余要消耗的数量
|
|
long remainingCount = count;
|
|
IBatch batch = redisManager.db.CreateBatch();
|
|
for (int i = 0; i < propNames.Length; i++)
|
|
{
|
|
long consumeCount = (int)Math.Min(currentCount[i], count);
|
|
if (consumeCount > 0)
|
|
{
|
|
string key = GetRedisKey(userid, propType, propNames[i]);
|
|
batch.StringDecrementAsync(key, consumeCount);
|
|
remainingCount -= consumeCount;
|
|
result.Add(new ActivityPropData()
|
|
{
|
|
PropName = propNames[i],
|
|
Id = (int)propType,
|
|
Count = consumeCount
|
|
});
|
|
}
|
|
}
|
|
|
|
batch.Execute();
|
|
return result;
|
|
}
|
|
}
|
|
} |