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 { private readonly Type ActivityPropDataBaseType = typeof(ActivityPropDataInfo); /// /// 道具信息 字典 /// private readonly Dictionary _activityPropData = new Dictionary(); /// /// 所有道具信息 /// private readonly List _activityPropDataInfos = new List(); 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); } } } /// /// 获取道具的过期时间 /// /// /// /// public DateTime GetExpireTime(ActivityPropType propType,string propName) { if (!_activityPropData.ContainsKey(propType)) { //没有这个数据,那么现在就过期 return DateTime.Now; } return _activityPropData[propType].GetExpireTime(propName); } /// /// 获取道具数据的KEY /// /// /// /// /// private string GetRedisKey(int userid, ActivityPropType propType, string propName) { return $"ActivityPropData:{userid}:{(int)propType}:{propName}"; } /// /// 获取某个玩家的所有道具数据 /// /// 玩家的userid /// public List GetActivityPropDatas(int userid) { List datas = new List(); List keys = new List(); 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; } /// /// 获取某个道具类型的 数据 /// /// 谁的 /// 道具类型 /// 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; } /// /// 获取某种道具的全部数量 /// /// /// /// 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; } /// /// 添加道具数据 /// /// /// /// 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(); } /// /// 添加道具数据 /// /// /// /// /// 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(); } /// /// 移除道具数据 /// /// /// /// /// 消耗的道具信息 public List 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 result = new List(); //剩余要消耗的数量 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; } } }