451 lines
15 KiB
C#
451 lines
15 KiB
C#
using System;
|
|||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Collections.Concurrent;
|
||
|
|
using System.Linq;
|
||
|
|
using System.Reflection;
|
||
|
|
using System.Text;
|
||
|
|
using System.Threading.Tasks;
|
||
|
|
using ChessGameDomain;
|
||
|
|
using Common.Redis;
|
||
|
|
using CommonDomain;
|
||
|
|
using CommonDomain.BaseModel;
|
||
|
|
using RedisHelper;
|
||
|
|
using RedisService.Param;
|
||
|
|
using UserDomain.Entity;
|
||
|
|
|
||
|
|
namespace RedisService
|
||
|
|
{
|
||
|
|
public class RedisService : IRedisService
|
||
|
|
{
|
||
|
|
private readonly ICache _cache;
|
||
|
|
private static readonly ConcurrentDictionary<string, RoomCacheEntry> GameRoomCache = new();
|
||
|
|
private static readonly TimeSpan GameRoomReadCacheDuration = TimeSpan.FromSeconds(3);
|
||
|
|
|
||
|
|
public RedisService(ICache cache)
|
||
|
|
{
|
||
|
|
_cache = cache;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
public RedisUserCid GetRedisUserCId(string userId)
|
||
|
|
{
|
||
|
|
return _cache.Get<RedisUserCid>(string.Format(RedisKey.UserCIDGID, userId));
|
||
|
|
}
|
||
|
|
public void SetRedisUserCId(RedisUserCid redisUser)
|
||
|
|
{
|
||
|
|
_cache.Insert(string.Format(RedisKey.UserCIDGID, redisUser.UserId), redisUser);
|
||
|
|
}
|
||
|
|
public void RemoveRedisUserCId(string userId)
|
||
|
|
{
|
||
|
|
_cache.Remove(string.Format(RedisKey.UserCIDGID, userId));
|
||
|
|
}
|
||
|
|
|
||
|
|
private static readonly ConcurrentDictionary<string, string> UserIdCache = new();
|
||
|
|
|
||
|
|
public string GetUserId(string cid)
|
||
|
|
{
|
||
|
|
UserIdCache.TryGetValue(cid, out var userId);
|
||
|
|
return userId;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void SetUserId(string cid, string userId)
|
||
|
|
{
|
||
|
|
UserIdCache[cid] = userId;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void RemoveUserId(string cid)
|
||
|
|
{
|
||
|
|
UserIdCache.TryRemove(cid, out _);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public string GetLoginUserId(string cid)
|
||
|
|
{
|
||
|
|
return _cache.Get<string>(string.Format(RedisKey.LoginCIDUser, cid));
|
||
|
|
}
|
||
|
|
public void SetLoginUserId(string cid, string userId)
|
||
|
|
{
|
||
|
|
_cache.Insert(string.Format(RedisKey.LoginCIDUser, cid), userId);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public IEnumerable<string> GetAllLoginUserIds()
|
||
|
|
{
|
||
|
|
var list = _cache.GetPatternList<string>(string.Format(RedisKey.LoginCIDUser, "*"), 100000);
|
||
|
|
return list;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void RemoveGameConfig()
|
||
|
|
{
|
||
|
|
_cache.Remove(RedisKey.GameConfig);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void SetActivityConfig(ActivityConfig config)
|
||
|
|
{
|
||
|
|
_cache.Insert<ActivityConfig>(RedisKey.ActivityConfig, config);
|
||
|
|
}
|
||
|
|
public ActivityConfig GetActivityConfig()
|
||
|
|
{
|
||
|
|
return _cache.Get<ActivityConfig>(RedisKey.ActivityConfig);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void RemoveActivityConfig()
|
||
|
|
{
|
||
|
|
_cache.Remove(RedisKey.ActivityConfig);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static string PlayerGoldKey(string roomId, string userId) => $"gold:{roomId}:{userId}";
|
||
|
|
private static string PlayerBulletsKey(string roomId, string userId) => $"bullets:{roomId}:{userId}";
|
||
|
|
private static string PlayerFactorKey(string roomId, string userId) => $"factor:{roomId}:{userId}";
|
||
|
|
private static string RoomKillFishKey(string roomId) => $"killfish:{roomId}";
|
||
|
|
private static string FishingTaskCountKey(string roomId, string userId, int taskEvent) => $"fishing:tasks:{roomId}:{userId}:{taskEvent}";
|
||
|
|
private static string FishingConsumeKey(string roomId, string userId) => $"fishing:consume:runtime:{roomId}:{userId}";
|
||
|
|
private static string FishingExpKey(string roomId, string userId) => $"fishing:exp:runtime:{roomId}:{userId}";
|
||
|
|
|
||
|
|
public long GetPlayerGold(string roomId, string userId)
|
||
|
|
{
|
||
|
|
return _cache.Get<long>(PlayerGoldKey(roomId, userId));
|
||
|
|
}
|
||
|
|
|
||
|
|
public void SetPlayerGold(string roomId, string userId, long gold)
|
||
|
|
{
|
||
|
|
_cache.Insert(PlayerGoldKey(roomId, userId), gold);
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool AddBulletId(string roomId, string userId, string bulletId)
|
||
|
|
{
|
||
|
|
return _cache.SetAdd(PlayerBulletsKey(roomId, userId), bulletId);
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool ExistsBulletId(string roomId, string userId, string bulletId)
|
||
|
|
{
|
||
|
|
return _cache.SetContains(PlayerBulletsKey(roomId, userId), bulletId);
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool RemoveBulletId(string roomId, string userId, string bulletId)
|
||
|
|
{
|
||
|
|
return _cache.SetRemove(PlayerBulletsKey(roomId, userId), bulletId);
|
||
|
|
}
|
||
|
|
|
||
|
|
public long GetBulletCount(string roomId, string userId)
|
||
|
|
{
|
||
|
|
return _cache.SetCount(PlayerBulletsKey(roomId, userId));
|
||
|
|
}
|
||
|
|
|
||
|
|
public void ClearBulletIds(string roomId, string userId)
|
||
|
|
{
|
||
|
|
_cache.Remove(PlayerBulletsKey(roomId, userId));
|
||
|
|
}
|
||
|
|
|
||
|
|
public void ClearPlayerRuntimeData(string roomId, string userId)
|
||
|
|
{
|
||
|
|
_cache.Remove(PlayerGoldKey(roomId, userId));
|
||
|
|
_cache.Remove(PlayerBulletsKey(roomId, userId));
|
||
|
|
_cache.Remove(PlayerFactorKey(roomId, userId));
|
||
|
|
}
|
||
|
|
|
||
|
|
public void AddFishingTaskProgress(string roomId, string userId, int taskEvent, long count)
|
||
|
|
{
|
||
|
|
if (count <= 0) return;
|
||
|
|
_cache.IncrBy(FishingTaskCountKey(roomId, userId, taskEvent), count);
|
||
|
|
}
|
||
|
|
|
||
|
|
public Dictionary<int, long> GetFishingTaskProgress(string roomId, string userId, IEnumerable<int> taskEvents)
|
||
|
|
{
|
||
|
|
var result = new Dictionary<int, long>();
|
||
|
|
foreach (var taskEvent in taskEvents.Distinct())
|
||
|
|
{
|
||
|
|
var count = _cache.Get<long>(FishingTaskCountKey(roomId, userId, taskEvent));
|
||
|
|
if (count > 0) result[taskEvent] = count;
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void ClearFishingTaskProgress(string roomId, string userId, IEnumerable<int> taskEvents)
|
||
|
|
{
|
||
|
|
foreach (var taskEvent in taskEvents.Distinct())
|
||
|
|
_cache.Remove(FishingTaskCountKey(roomId, userId, taskEvent));
|
||
|
|
}
|
||
|
|
|
||
|
|
public void AddFishingConsumeProgress(string roomId, string userId, long count)
|
||
|
|
{
|
||
|
|
if (count > 0) _cache.IncrBy(FishingConsumeKey(roomId, userId), count);
|
||
|
|
}
|
||
|
|
|
||
|
|
public long GetFishingConsumeProgress(string roomId, string userId) => _cache.Get<long>(FishingConsumeKey(roomId, userId));
|
||
|
|
|
||
|
|
public void AddFishingExpProgress(string roomId, string userId, long count)
|
||
|
|
{
|
||
|
|
if (count > 0) _cache.IncrBy(FishingExpKey(roomId, userId), count);
|
||
|
|
}
|
||
|
|
|
||
|
|
public long GetFishingExpProgress(string roomId, string userId) => _cache.Get<long>(FishingExpKey(roomId, userId));
|
||
|
|
|
||
|
|
public void ClearFishingRuntimeProgress(string roomId, string userId)
|
||
|
|
{
|
||
|
|
_cache.Remove(FishingConsumeKey(roomId, userId));
|
||
|
|
_cache.Remove(FishingExpKey(roomId, userId));
|
||
|
|
}
|
||
|
|
|
||
|
|
public PlayerFactor GetPlayerFactor(string roomId, string userId)
|
||
|
|
{
|
||
|
|
return _cache.Get<PlayerFactor>(PlayerFactorKey(roomId, userId));
|
||
|
|
}
|
||
|
|
|
||
|
|
public void SetPlayerFactor(string roomId, string userId, PlayerFactor factor)
|
||
|
|
{
|
||
|
|
_cache.Insert(PlayerFactorKey(roomId, userId), factor);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void RemovePlayerFactor(string roomId, string userId)
|
||
|
|
{
|
||
|
|
_cache.Remove(PlayerFactorKey(roomId, userId));
|
||
|
|
}
|
||
|
|
|
||
|
|
public List<string> GetKillFishIds(string roomId)
|
||
|
|
{
|
||
|
|
return _cache.SetMembers<string>(RoomKillFishKey(roomId));
|
||
|
|
}
|
||
|
|
|
||
|
|
public void AddKillFishId(string roomId, string fishId)
|
||
|
|
{
|
||
|
|
_cache.SetAdd(RoomKillFishKey(roomId), fishId);
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool ContainsKillFishId(string roomId, string fishId)
|
||
|
|
{
|
||
|
|
return _cache.SetContains(RoomKillFishKey(roomId), fishId);
|
||
|
|
}
|
||
|
|
|
||
|
|
public List<ChessGameRoom> GetAllPlayingChessRooms()
|
||
|
|
{
|
||
|
|
var allRooms = GetAllChessRooms();
|
||
|
|
if (allRooms == null)
|
||
|
|
return new List<ChessGameRoom>();
|
||
|
|
|
||
|
|
return allRooms.Where(r => r.state == 2).ToList();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public void SetFishingKillConfig(FishingKillConfig config)
|
||
|
|
{
|
||
|
|
_cache.Insert(RedisKey.FishingKillConfig, config);
|
||
|
|
}
|
||
|
|
public FishingKillConfig GetFishingKillConfig()
|
||
|
|
{
|
||
|
|
return _cache.Get<FishingKillConfig>(RedisKey.FishingKillConfig);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void SetFishSpawnConfig(string json)
|
||
|
|
{
|
||
|
|
_cache.Insert(RedisKey.FishSpawnConfig, json);
|
||
|
|
}
|
||
|
|
|
||
|
|
public string GetFishSpawnConfig()
|
||
|
|
{
|
||
|
|
return _cache.Get<string>(RedisKey.FishSpawnConfig);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public void SetGameRoom(RedisGameRoom gameRoom)
|
||
|
|
{
|
||
|
|
string Partition = $"{(int)gameRoom.GameType}{gameRoom.RoomLevel}{gameRoom.RoomPartition}";
|
||
|
|
_cache.Insert<RedisGameRoom>(string.Format(RedisKey.GameRoomIdKey, Partition, gameRoom.RoomId), gameRoom);
|
||
|
|
GameRoomCache[gameRoom.RoomId] = new RoomCacheEntry(gameRoom, DateTime.UtcNow, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
public RedisGameRoom GetGameRoom(string roomId)
|
||
|
|
{
|
||
|
|
if (string.IsNullOrWhiteSpace(roomId))
|
||
|
|
return null;
|
||
|
|
|
||
|
|
var partition = roomId.Length >= 3 ? roomId.Substring(0, 3) : roomId.PadRight(3, '0');
|
||
|
|
var room = _cache.Get<RedisGameRoom>(string.Format(RedisKey.GameRoomIdKey, partition, roomId));
|
||
|
|
if (room != null)
|
||
|
|
GameRoomCache[roomId] = new RoomCacheEntry(room, DateTime.UtcNow, false);
|
||
|
|
else
|
||
|
|
GameRoomCache.TryRemove(roomId, out _);
|
||
|
|
return room;
|
||
|
|
}
|
||
|
|
public IEnumerable<RedisGameRoom> GetGameRoomList(string partition)
|
||
|
|
{
|
||
|
|
var list = _cache.GetPatternList<RedisGameRoom>(string.Format(RedisKey.GameRoomIdKey, partition, "*"), 100);
|
||
|
|
|
||
|
|
return list;
|
||
|
|
}
|
||
|
|
|
||
|
|
public IEnumerable<RedisGameRoom> GetGameRoomAllList()
|
||
|
|
{
|
||
|
|
var list = _cache.GetPatternList<RedisGameRoom>(string.Format(RedisKey.GameRoomIdKey, "*", "*"), 10000);
|
||
|
|
|
||
|
|
return list;
|
||
|
|
}
|
||
|
|
|
||
|
|
public string GetPendingFishRoomId(string userId)
|
||
|
|
{
|
||
|
|
if (string.IsNullOrWhiteSpace(userId))
|
||
|
|
return string.Empty;
|
||
|
|
|
||
|
|
var rooms = GetGameRoomAllList();
|
||
|
|
if (rooms == null)
|
||
|
|
return string.Empty;
|
||
|
|
|
||
|
|
var room = rooms.FirstOrDefault(r =>
|
||
|
|
r != null && r.Players != null && r.Players.Any(p => p.UserId == userId && !p.IsBot));
|
||
|
|
return room?.RoomId ?? string.Empty;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void RemoveGameRoom(string partition)
|
||
|
|
{
|
||
|
|
_cache.Clear(string.Format(RedisKey.GameRoomIdKey, partition, "*"));
|
||
|
|
foreach (var roomId in GameRoomCache.Keys.Where(id => id.StartsWith(partition, StringComparison.Ordinal)))
|
||
|
|
GameRoomCache.TryRemove(roomId, out _);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void RemoveGameRoomAll()
|
||
|
|
{
|
||
|
|
_cache.Clear(string.Format(RedisKey.GameRoomIdKey, "*", "*"), 50000);
|
||
|
|
GameRoomCache.Clear();
|
||
|
|
}
|
||
|
|
|
||
|
|
private sealed record RoomCacheEntry(RedisGameRoom Room, DateTime CachedAt, bool IsLocallyOwned);
|
||
|
|
|
||
|
|
|
||
|
|
public void SetGameConfig(GameConfig gameConfig)
|
||
|
|
{
|
||
|
|
_cache.Insert<GameConfig>(RedisKey.GameConfig, gameConfig);
|
||
|
|
}
|
||
|
|
public GameConfig GetGameConfig()
|
||
|
|
{
|
||
|
|
return _cache.Get<GameConfig>(RedisKey.GameConfig);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
public void SetSystemGoldDay(long amount)
|
||
|
|
{
|
||
|
|
_cache.Insert<long>(RedisKey.SystemGoldDayKey, amount);
|
||
|
|
}
|
||
|
|
public void AddSystemGoldDay(long gold)
|
||
|
|
{
|
||
|
|
_cache.IncrBy(RedisKey.SystemGoldDayKey, gold);
|
||
|
|
}
|
||
|
|
public long GetSystemGoldDay()
|
||
|
|
{
|
||
|
|
return _cache.Get<long>(RedisKey.SystemGoldDayKey);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public void SetChessRoom(ChessGameRoom room)
|
||
|
|
{
|
||
|
|
string key = string.Format(RedisKey.ChessRoomKey, room.RoomId);
|
||
|
|
_cache.Insert<ChessGameRoom>(key, room);
|
||
|
|
}
|
||
|
|
|
||
|
|
public ChessGameRoom GetChessRoom(string roomId)
|
||
|
|
{
|
||
|
|
string key = string.Format(RedisKey.ChessRoomKey, roomId);
|
||
|
|
return _cache.Get<ChessGameRoom>(key);
|
||
|
|
}
|
||
|
|
|
||
|
|
public List<ChessGameRoom> GetAllChessRooms()
|
||
|
|
{
|
||
|
|
var pattern = RedisKeyGenerator.GameKey("chess:room:*");
|
||
|
|
return _cache.GetPatternList<ChessGameRoom>(pattern, 10000)
|
||
|
|
?.Select(r => r ?? new ChessGameRoom())
|
||
|
|
.ToList() ?? new List<ChessGameRoom>();
|
||
|
|
}
|
||
|
|
|
||
|
|
public string GetPendingChessRoomId(string userId)
|
||
|
|
{
|
||
|
|
if (string.IsNullOrWhiteSpace(userId))
|
||
|
|
return string.Empty;
|
||
|
|
|
||
|
|
var rooms = GetAllChessRooms();
|
||
|
|
if (rooms == null || rooms.Count == 0)
|
||
|
|
return string.Empty;
|
||
|
|
|
||
|
|
var room = rooms.FirstOrDefault(r =>
|
||
|
|
r != null && r.state == 2 && !r.IsGameEnded
|
||
|
|
&& r.users != null && r.users.Any(u => u.userId == userId));
|
||
|
|
return room?.RoomId ?? string.Empty;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void RemoveChessRoom(string roomId)
|
||
|
|
{
|
||
|
|
string key = string.Format(RedisKey.ChessRoomKey, roomId);
|
||
|
|
_cache.Remove(key);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void ClearAllChessRooms()
|
||
|
|
{
|
||
|
|
var pattern = RedisKeyGenerator.GameKey("chess:room:*");
|
||
|
|
_cache.Clear(pattern, 50000);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void ClearAllGameRooms()
|
||
|
|
{
|
||
|
|
var pattern = RedisKeyGenerator.GameKey("room:model:*");
|
||
|
|
_cache.Clear(pattern, 50000);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void ClearAllUserMappings()
|
||
|
|
{
|
||
|
|
var cidPattern = RedisKeyGenerator.UserKey("cid:*");
|
||
|
|
var uidPattern = RedisKeyGenerator.UserKey("uid:*");
|
||
|
|
_cache.Clear(cidPattern, 50000);
|
||
|
|
_cache.Clear(uidPattern, 50000);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void ClearAllLoginUserIds()
|
||
|
|
{
|
||
|
|
var cidPattern = RedisKeyGenerator.UserKey("cid:*");
|
||
|
|
var uidPattern = RedisKeyGenerator.UserKey("uid:*");
|
||
|
|
_cache.Clear(cidPattern, 100000);
|
||
|
|
_cache.Clear(uidPattern, 100000);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public void RemoveLoginUserId(string cid)
|
||
|
|
{
|
||
|
|
_cache.Remove(RedisKey.LoginCIDUser.Replace("{0}", cid));
|
||
|
|
}
|
||
|
|
|
||
|
|
public void SetVerificationCode(string phone, string code)
|
||
|
|
{
|
||
|
|
_cache.Insert<string>(RedisKey.VerificationCode.Replace("{0}", phone), code, TimeSpan.FromMinutes(5));
|
||
|
|
}
|
||
|
|
|
||
|
|
public string GetVerificationCode(string phone)
|
||
|
|
{
|
||
|
|
return _cache.Get<string>(RedisKey.VerificationCode.Replace("{0}", phone));
|
||
|
|
}
|
||
|
|
|
||
|
|
public void RemoveVerificationCode(string phone)
|
||
|
|
{
|
||
|
|
_cache.Remove(RedisKey.VerificationCode.Replace("{0}", phone));
|
||
|
|
}
|
||
|
|
|
||
|
|
public long IncrBy(string key, long value)
|
||
|
|
{
|
||
|
|
return _cache.IncrBy(key, value);
|
||
|
|
}
|
||
|
|
|
||
|
|
public string GetString(string key)
|
||
|
|
{
|
||
|
|
return _cache.Get<string>(key);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void SetString(string key, string value)
|
||
|
|
{
|
||
|
|
_cache.Insert(key, value);
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|