Files
hjha-server/GlobalSever/Manager/ActivityPropManager.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

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;
}
}
}