修改问题
This commit is contained in:
parent
d6740c92dd
commit
b556c4c23b
|
|
@ -149,7 +149,7 @@ public class PlayGameController : CloudGamingControllerBase
|
|||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Authorize]
|
||||
public async Task<BaseResponse<object>> ReconPlayGameAsync([FromBody] ReconPlayGameSettings reconPlayGameSettings)
|
||||
public async Task<BaseResponse<object>> ReconPlayGameAsync([FromBody] ReconPlayGameRequest reconPlayGameSettings)
|
||||
{
|
||||
PlayGameBLL playGameBLL = new PlayGameBLL(ServiceProvider, JYApi);
|
||||
return await playGameBLL.ReconPlayGame(reconPlayGameSettings);
|
||||
|
|
|
|||
|
|
@ -149,6 +149,17 @@ namespace CloudGaming.Code.AppExtend
|
|||
{
|
||||
return RedisConnection.GetRedis(appConfig.RedisConnectionString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="redisConnection"></param>
|
||||
/// <returns></returns>
|
||||
public static IServer GetRedisServer(this AppConfig appConfig)
|
||||
{
|
||||
return RedisConnection.GetServer(appConfig.RedisConnectionString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取Dao
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ namespace CloudGaming.Code.Contract
|
|||
Task<JYApiResponse<Dictionary<string, object>>> DisplayGrade([Body(BodySerializationMethod.UrlEncoded)] DisplayGradeSettings playGameQueue);
|
||||
|
||||
/// <summary>
|
||||
/// 切换视频等级
|
||||
/// 重连会话
|
||||
/// </summary>
|
||||
/// <param name="playGameQueue"></param>
|
||||
/// <returns></returns>
|
||||
|
|
@ -84,7 +84,7 @@ namespace CloudGaming.Code.Contract
|
|||
/// <param name="requestBase"></param>
|
||||
/// <returns></returns>
|
||||
[Post("/jyapi/myScList")]
|
||||
Task<JYApiResponse<Dictionary<string, object>>> MyScList([Body(BodySerializationMethod.UrlEncoded)] RequestBaseModel requestBase);
|
||||
Task<JYApiResponse<Dictionary<string, object>>> MyScList([Body(BodySerializationMethod.UrlEncoded)] JYRequestParameter parameter);
|
||||
/// <summary>
|
||||
/// 获取会话列表
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ using CloudGaming.DtoModel.PlayGame;
|
|||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using Org.BouncyCastle.Asn1.Ocsp;
|
||||
|
||||
|
||||
namespace CloudGaming.Code.Game;
|
||||
|
||||
|
|
@ -481,10 +483,7 @@ public class PlayGameBLL : CloudGamingBase
|
|||
/// <returns></returns>
|
||||
public async Task<BaseResponse<object>> GetMyScList(string sn)
|
||||
{
|
||||
var requestParmat = new RequestBaseModel()
|
||||
{
|
||||
Sn = sn,
|
||||
};
|
||||
var requestParmat = new JYRequestParameter(sn, _UserId);
|
||||
var response = await JYApi.MyScList(requestParmat);
|
||||
if (response.IsSuccess)
|
||||
{
|
||||
|
|
@ -497,27 +496,32 @@ public class PlayGameBLL : CloudGamingBase
|
|||
/// <summary>
|
||||
/// 重连会话
|
||||
/// </summary>
|
||||
/// <param name="sc_id"></param>
|
||||
/// <param name="display_grade"></param>
|
||||
/// <param name="model_name"></param>
|
||||
/// <param name="sn"></param>
|
||||
/// <param name="cpu"></param>
|
||||
/// <param name="reconPlayGameRequest"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<BaseResponse<object>> ReconPlayGame(ReconPlayGameSettings reconPlayGameSettings)
|
||||
public async Task<BaseResponse<dynamic>> ReconPlayGame(ReconPlayGameRequest reconPlayGameRequest)
|
||||
{
|
||||
var setting = new ReconPlayGameSettings()
|
||||
var setting = new ReconPlayGameSettings(reconPlayGameRequest.Sn, _UserId)
|
||||
{
|
||||
ScId = reconPlayGameSettings.ScId,
|
||||
DisplayGrade = reconPlayGameSettings.DisplayGrade,
|
||||
Cpu = reconPlayGameSettings.Cpu,
|
||||
ModelName = reconPlayGameSettings.ModelName,
|
||||
Sn = reconPlayGameSettings.Sn,
|
||||
ScId = reconPlayGameRequest.ScId,
|
||||
DisplayGrade = reconPlayGameRequest.DisplayGrade,
|
||||
Cpu = reconPlayGameRequest.Cpu,
|
||||
ModelName = reconPlayGameRequest.ModelName,
|
||||
};
|
||||
var response = await JYApi.ReconPlayGame(setting);
|
||||
if (response.IsSuccess)
|
||||
var jyResponseData = await JYApi.ReconPlayGame(setting);
|
||||
if (jyResponseData.IsSuccess)
|
||||
{
|
||||
return new BaseResponse<object>(ResponseCode.Success, "", response.Data) { };
|
||||
var gameInfo = await PlayGameExtend.PlayGameRecon(this, _UserId, reconPlayGameRequest.ScId);
|
||||
var gameResponse1 = JsonConvert.DeserializeObject<Dictionary<string, object>>(jyResponseData.ResponseContent);
|
||||
if (gameResponse1 != null && gameResponse1.TryGetValue("data", out var xxx))
|
||||
{
|
||||
if (gameInfo != null)
|
||||
{
|
||||
await gameInfo.SaveChangesAsync(this);
|
||||
}
|
||||
return new BaseResponse<dynamic>(ResponseCode.Success, "", new { GameId = gameInfo?.GameId, GameData = JsonConvert.SerializeObject(xxx) });
|
||||
}
|
||||
|
||||
}
|
||||
throw response.ToMessageBox();
|
||||
throw jyResponseData.ToMessageBox();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
using AgileConfig.Client;
|
||||
|
||||
using CloudGaming.Code.DataAccess;
|
||||
using CloudGaming.Code.DataAccess.MultiTenantUtil;
|
||||
using CloudGaming.DtoModel.Account.User;
|
||||
using CloudGaming.DtoModel.Game;
|
||||
using CloudGaming.DtoModel.JY;
|
||||
|
|
@ -8,13 +11,35 @@ using HuanMeng.DotNetCore.Redis;
|
|||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using StackExchange.Redis;
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace CloudGaming.Code.Game
|
||||
{
|
||||
public static class PlayGameExtend
|
||||
{
|
||||
private static string GetPlayGameKey(string gameId, int userId) => $"PlayGame:{gameId}:{userId}";
|
||||
|
||||
/// <summary>
|
||||
/// 初始化app
|
||||
/// </summary>
|
||||
/// <param name="builder"></param>
|
||||
/// <returns></returns>
|
||||
public static IHostApplicationBuilder AddPlayGameServer(this WebApplicationBuilder builder)
|
||||
{
|
||||
|
||||
builder.Services.AddHostedService<PlayGameService>();
|
||||
return builder;
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="gameId"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetPlayGameKeyPrefix { get; set; } = $"PlayGame";
|
||||
public static string GetPlayGameKey(string gameId, int userId) => $"PlayGame:{gameId}:{userId}";
|
||||
/// <summary>
|
||||
/// 获取用户游戏缓存
|
||||
/// </summary>
|
||||
|
|
@ -91,7 +116,7 @@ namespace CloudGaming.Code.Game
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化
|
||||
/// 结束游戏
|
||||
/// </summary>
|
||||
/// <param name="playGameUserInfo"></param>
|
||||
/// <param name="sn"></param>
|
||||
|
|
@ -104,10 +129,10 @@ namespace CloudGaming.Code.Game
|
|||
if (playGameUserInfo.GameStatus != PlayGameStatus.游戏结束)
|
||||
{
|
||||
playGameUserInfo.GameStatus = PlayGameStatus.游戏结束;
|
||||
playGameUserInfo.GameUserOperation.Add(new PlayGameUserOperation()
|
||||
playGameUserInfo.GameUserOperation.Add(new PlayGameUserOperation(jYApiRespnse)
|
||||
{
|
||||
OperationDateTime = DateTime.Now,
|
||||
Content = "游戏结束"
|
||||
Content = "游戏结束",
|
||||
});
|
||||
playGameUserInfo.LastDateTime = DateTime.Now;
|
||||
}
|
||||
|
|
@ -176,6 +201,15 @@ namespace CloudGaming.Code.Game
|
|||
{
|
||||
if (playGameUserInfo.GameStatus != PlayGameStatus.游戏中)
|
||||
{
|
||||
|
||||
if (playGameUserInfo.GameStatus == PlayGameStatus.游戏掉线)
|
||||
{
|
||||
playGameUserInfo.GameUserOperation.Add(new PlayGameUserOperation()
|
||||
{
|
||||
OperationDateTime = DateTime.Now,
|
||||
Content = "用户游戏掉线重连成功",
|
||||
});
|
||||
}
|
||||
playGameUserInfo.GameStatus = PlayGameStatus.游戏中;
|
||||
}
|
||||
playGameUserInfo.PlayGameHeartbeatAt = DateTime.Now;
|
||||
|
|
@ -279,6 +313,80 @@ namespace CloudGaming.Code.Game
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 游戏掉线
|
||||
/// </summary>
|
||||
/// <param name="playGameUserInfo"></param>
|
||||
/// <returns></returns>
|
||||
public static bool PlayGameUserNotAction(this PlayGameUserInfo playGameUserInfo)
|
||||
{
|
||||
if (playGameUserInfo.GameStatus != PlayGameStatus.游戏掉线)
|
||||
{
|
||||
playGameUserInfo.GameStatus = PlayGameStatus.游戏掉线;
|
||||
playGameUserInfo.GameUserOperation.Add(new PlayGameUserOperation()
|
||||
{
|
||||
Content = $"用户游戏掉线,上一次心跳时间{playGameUserInfo.PlayGameHeartbeatAt?.ToString("yyyy-MM-dd HH:mm:ss")};",
|
||||
OperationDateTime = DateTime.Now,
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="redis"></param>
|
||||
/// <param name="redisServer"></param>
|
||||
/// <param name="keyPattern"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<List<PlayGameUserInfo?>> GetPlayGameUserInfoList(IDatabase redis, IServer redisServer, string keyPattern)
|
||||
{
|
||||
var keys = await redisServer.ScanKeysAsync(keyPattern, 2000).ConfigureAwait(false);
|
||||
|
||||
var tasks = keys.Select(async gameKey =>
|
||||
{
|
||||
var gameInfo = await redis.StringGetAsync<PlayGameUserInfo>(gameKey).ConfigureAwait(false);
|
||||
return gameInfo;
|
||||
});
|
||||
|
||||
var gameInfoList = (await Task.WhenAll(tasks).ConfigureAwait(false)).Where(x => x != null).ToList();
|
||||
return gameInfoList;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 游戏掉线
|
||||
/// </summary>
|
||||
/// <param name="playGameUserInfo"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<PlayGameUserInfo> PlayGameRecon(CloudGamingBase cloudGamingBase, int userId, int scId)
|
||||
{
|
||||
var list = await GetPlayGameUserInfoList(cloudGamingBase.RedisCache, cloudGamingBase.RedisServerCache, $"{GetPlayGameKeyPrefix}:*:{userId}");
|
||||
if (list != null && list.Count > 0)
|
||||
{
|
||||
var playGameUserInfo = list.Where(it => it.ScId == scId).FirstOrDefault();
|
||||
if (playGameUserInfo == null)
|
||||
{
|
||||
playGameUserInfo = list[0];
|
||||
}
|
||||
if (playGameUserInfo != null)
|
||||
{
|
||||
if (playGameUserInfo.GameStatus != PlayGameStatus.游戏掉线)
|
||||
{
|
||||
playGameUserInfo.GameStatus = PlayGameStatus.游戏掉线;
|
||||
playGameUserInfo.GameUserOperation.Add(new PlayGameUserOperation()
|
||||
{
|
||||
Content = $"用户游戏掉线,上一次心跳时间{playGameUserInfo.PlayGameHeartbeatAt?.ToString("yyyy-MM-dd HH:mm:ss")};",
|
||||
OperationDateTime = DateTime.Now,
|
||||
});
|
||||
}
|
||||
}
|
||||
return playGameUserInfo;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存缓存到redis中
|
||||
/// </summary>
|
||||
|
|
@ -286,6 +394,19 @@ namespace CloudGaming.Code.Game
|
|||
/// <param name="cloudGamingBase"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<bool> SaveChangesAsync(this PlayGameUserInfo playGameUserInfo, CloudGamingBase cloudGamingBase)
|
||||
{
|
||||
return await SaveChangesAsync(playGameUserInfo, cloudGamingBase.Dao, cloudGamingBase.RedisCache);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 保存缓存到redis中
|
||||
/// </summary>
|
||||
/// <param name="playGameUserInfo"></param>
|
||||
/// <param name="dao"></param>
|
||||
/// <param name="redisDatabase"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<bool> SaveChangesAsync(this PlayGameUserInfo playGameUserInfo, DAO dao, IDatabase redisDatabase)
|
||||
{
|
||||
playGameUserInfo.LastDateTime = DateTime.Now;
|
||||
var redisGameKey = GetPlayGameKey(playGameUserInfo.GameId, playGameUserInfo.UserId);
|
||||
|
|
@ -294,7 +415,7 @@ namespace CloudGaming.Code.Game
|
|||
if (playGameUserInfo.DiamondListId > 0)
|
||||
{
|
||||
//设置游玩记录
|
||||
var userGameListLog = await cloudGamingBase.Dao.DaoPhone.Context.T_User_GameList.FirstOrDefaultAsync(it => it.Id == playGameUserInfo.DiamondListId);
|
||||
var userGameListLog = await dao.DaoPhone.Context.T_User_GameList.FirstOrDefaultAsync(it => it.Id == playGameUserInfo.DiamondListId);
|
||||
if (userGameListLog != null)
|
||||
{
|
||||
userGameListLog.Status = (int)PlayGameStatus.游戏结束;
|
||||
|
|
@ -304,12 +425,12 @@ namespace CloudGaming.Code.Game
|
|||
userGameListLog.PlaySeconds = (int)t.TotalSeconds;
|
||||
userGameListLog.PlayTime = playTime;
|
||||
userGameListLog.UpdateTime = DateTime.Now;
|
||||
await cloudGamingBase.Dao.DaoPhone.Context.SaveChangesAsync();
|
||||
await dao.DaoPhone.Context.SaveChangesAsync();
|
||||
//设置游玩历史
|
||||
var userId = playGameUserInfo.UserId;
|
||||
var gameId = playGameUserInfo.GameId;
|
||||
//设置用户游玩历史
|
||||
var playGameTime = await cloudGamingBase.Dao.DaoPhone.Context.T_User_PlayGameTime.Where(it => it.UserId == userId && it.GameId == gameId).FirstOrDefaultAsync();
|
||||
var playGameTime = await dao.DaoPhone.Context.T_User_PlayGameTime.Where(it => it.UserId == userId && it.GameId == gameId).FirstOrDefaultAsync();
|
||||
if (playGameTime == null)
|
||||
{
|
||||
playGameTime = new T_User_PlayGameTime()
|
||||
|
|
@ -323,26 +444,25 @@ namespace CloudGaming.Code.Game
|
|||
UpdateTime = DateTime.Now,
|
||||
UserId = userId,
|
||||
};
|
||||
await cloudGamingBase.Dao.DaoPhone.Context.T_User_PlayGameTime.AddAsync(playGameTime);
|
||||
await dao.DaoPhone.Context.T_User_PlayGameTime.AddAsync(playGameTime);
|
||||
}
|
||||
playGameTime.PlayTime += playTime;
|
||||
playGameTime.UpdateTime = DateTime.Now;
|
||||
playGameTime.DiamondPlayTime += playTime;
|
||||
await cloudGamingBase.Dao.DaoPhone.Context.SaveChangesAsync();
|
||||
await dao.DaoPhone.Context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
var playGameLog = playGameUserInfo.ToGamePlayGameLog();
|
||||
if (playGameLog != null)
|
||||
{
|
||||
await cloudGamingBase.Dao.DaoPhone.Context.T_Game_PlayGameLog.AddAsync(playGameLog);
|
||||
await cloudGamingBase.Dao.DaoPhone.Context.SaveChangesAsync();
|
||||
await dao.DaoPhone.Context.T_Game_PlayGameLog.AddAsync(playGameLog);
|
||||
await dao.DaoPhone.Context.SaveChangesAsync();
|
||||
}
|
||||
return await cloudGamingBase.RedisCache.KeyDeleteAsync(redisGameKey);
|
||||
return await redisDatabase.KeyDeleteAsync(redisGameKey);
|
||||
}
|
||||
return await cloudGamingBase.RedisCache.StringSetAsync(redisGameKey, playGameUserInfo, TimeSpan.FromMinutes(10));
|
||||
return await redisDatabase.StringSetAsync(redisGameKey, playGameUserInfo, TimeSpan.FromMinutes(10));
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
119
src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameProcessor.cs
Normal file
119
src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameProcessor.cs
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
using CloudGaming.Code.AppExtend;
|
||||
using CloudGaming.Code.Contract;
|
||||
using CloudGaming.Code.DataAccess;
|
||||
using CloudGaming.Code.JY;
|
||||
using CloudGaming.DtoModel.PlayGame;
|
||||
|
||||
using Flurl.Util;
|
||||
|
||||
using HuanMeng.DotNetCore.Processors;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
using Refit;
|
||||
|
||||
using StackExchange.Redis;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using static SKIT.FlurlHttpClient.Wechat.TenpayV3.Models.CreatePayDevicePrinterPrintOrderRequest.Types.Table.Types;
|
||||
|
||||
namespace CloudGaming.Code.Game;
|
||||
|
||||
/// <summary>
|
||||
/// 游戏服务
|
||||
/// </summary>
|
||||
public class PlayGameProcessor(IServiceProvider serviceProvider) : ThreadProcessor
|
||||
{
|
||||
protected override async void Proc_Do()
|
||||
{
|
||||
while (_isRunning)
|
||||
{
|
||||
// 多项目配置
|
||||
var appConfigs = AppConfigurationExtend.AppConfigs
|
||||
.Select(it => it.Value)
|
||||
.Where(it => it.DomainName != "default")
|
||||
.ToList();
|
||||
|
||||
var tasks = appConfigs.Select(ProcessAppConfig).ToList();
|
||||
|
||||
// 等待所有任务完成
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
// 使用异步延迟代替阻塞线程
|
||||
await Task.Delay(5);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessAppConfig(AppConfig appConfig)
|
||||
{
|
||||
var userNotActionDisconnect = DateTime.Now.AddSeconds(-appConfig.GameConfig.UserNotActionDisconnect);
|
||||
var userNotActionEndGame = DateTime.Now.AddSeconds(-appConfig.GameConfig.UserNotActionEndGame);
|
||||
|
||||
using var scope = serviceProvider.CreateScope();
|
||||
var dao = scope.ServiceProvider.GetDAO(appConfig);
|
||||
var redis = appConfig.GetRedisDataBase();
|
||||
var redisServer = appConfig.GetRedisServer();
|
||||
|
||||
var keyPattern = $"{PlayGameExtend.GetPlayGameKeyPrefix}:*";
|
||||
List<PlayGameUserInfo?> gameInfoList = await GetPlayGameUserInfoList(redis, redisServer, keyPattern).ConfigureAwait(false);
|
||||
|
||||
// 处理未操作断线的玩家
|
||||
var userPlayGameNotActionEndGame = gameInfoList
|
||||
.Where(it => it.GameStatus == PlayGameStatus.游戏掉线 && it.PlayGameHeartbeatAt < userNotActionEndGame)
|
||||
.ToList();
|
||||
|
||||
foreach (var user in userPlayGameNotActionEndGame)
|
||||
{
|
||||
await EndGameAsync(user, appConfig, dao, redis).ConfigureAwait(false);
|
||||
gameInfoList.Remove(user);
|
||||
}
|
||||
|
||||
// 处理未操作标记为掉线的玩家
|
||||
var userPlayGameNotAction = gameInfoList
|
||||
.Where(it => it.GameStatus == PlayGameStatus.游戏中 && it.PlayGameHeartbeatAt < userNotActionDisconnect)
|
||||
.ToList();
|
||||
|
||||
foreach (var user in userPlayGameNotAction)
|
||||
{
|
||||
//将用户标记为短线状态
|
||||
user.PlayGameUserNotAction();
|
||||
await user.SaveChangesAsync(dao, redis).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<List<PlayGameUserInfo?>> GetPlayGameUserInfoList(IDatabase redis, IServer redisServer, string keyPattern)
|
||||
{
|
||||
var keys = await redisServer.ScanKeysAsync(keyPattern, 2000).ConfigureAwait(false);
|
||||
|
||||
var tasks = keys.Select(async gameKey =>
|
||||
{
|
||||
var gameInfo = await redis.StringGetAsync<PlayGameUserInfo>(gameKey).ConfigureAwait(false);
|
||||
return gameInfo;
|
||||
});
|
||||
|
||||
var gameInfoList = (await Task.WhenAll(tasks).ConfigureAwait(false)).Where(x => x != null).ToList();
|
||||
return gameInfoList;
|
||||
}
|
||||
|
||||
private async Task EndGameAsync(PlayGameUserInfo user, AppConfig appConfig, DAO dao, IDatabase redis)
|
||||
{
|
||||
using HttpClient httpClient = new HttpClient(new JYApiAppConfigHandler(appConfig, user.Ip));
|
||||
var jyApi = RestService.For<IJYApi>(httpClient);
|
||||
|
||||
var playGameCommonSetting = new PlayGameCommonSetting
|
||||
{
|
||||
ScId = user.ScId,
|
||||
Sn = user.Sn
|
||||
};
|
||||
|
||||
var jyResponse = await jyApi.StopGame(playGameCommonSetting).ConfigureAwait(false);
|
||||
|
||||
user.ExitPlayGame(jyResponse);
|
||||
await user.SaveChangesAsync(dao, redis).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,16 +6,29 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace CloudGaming.Code.Game;
|
||||
|
||||
/// <summary>
|
||||
/// 玩游戏服务
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider"></param>
|
||||
public class PlayGameService(IServiceProvider serviceProvider) : IHostedService
|
||||
{
|
||||
PlayGameProcessor? playGameProcessor = null;
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
//AppConfigurationExtend.AppConfigs.Select(it => it.Value).Where(it => it.DomainName != "default").ToList();
|
||||
throw new NotImplementedException();
|
||||
AppConfigurationExtend.AppConfigs.Select(it => it.Value).Where(it => it.DomainName != "default").ToList();
|
||||
//throw new NotImplementedException();
|
||||
playGameProcessor = new PlayGameProcessor(serviceProvider) { };
|
||||
playGameProcessor.Run();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (playGameProcessor != null)
|
||||
{
|
||||
playGameProcessor.Stop();
|
||||
playGameProcessor.Dispose();
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
|
||||
using CloudGaming.AppConfigModel;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CloudGaming.Code.JY
|
||||
{
|
||||
public class JYApiAppConfigHandler : JYApiHandler
|
||||
{
|
||||
protected AppConfig AppConfig { get; set; }
|
||||
protected string Ip { get; set; }
|
||||
public JYApiAppConfigHandler(AppConfig appConfig, string ip) : base(null)
|
||||
{
|
||||
AppConfig = appConfig;
|
||||
Ip = ip;
|
||||
}
|
||||
|
||||
//protected new async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// await SetRequest(request);
|
||||
// var sw = Stopwatch.StartNew();
|
||||
// var response = await base.SendAsync(request, cancellationToken);
|
||||
// sw.Stop();
|
||||
// if (response.IsSuccessStatusCode)
|
||||
// {
|
||||
// await AttachDebugInfoAsync(request, response, sw.Elapsed.TotalMilliseconds.ToString());
|
||||
// }
|
||||
// return response;
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// // 可根据实际需要扩展异常处理逻辑
|
||||
// throw new HttpRequestException("发送请求时发生错误。", ex);
|
||||
// }
|
||||
//}
|
||||
protected override async Task SetRequest(HttpRequestMessage request)
|
||||
{
|
||||
|
||||
|
||||
UpdateRequestUri(request, AppConfig.GameConfig.BsUrl);
|
||||
|
||||
if (request.Content is FormUrlEncodedContent)
|
||||
{
|
||||
|
||||
await UpdateRequestContentAsync(request, AppConfig, Ip);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
|
|
@ -10,11 +12,14 @@ namespace CloudGaming.Code.JY;
|
|||
/// </summary>
|
||||
public class JYApiHandler : DelegatingHandler
|
||||
{
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
protected readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
public JYApiHandler(IHttpContextAccessor httpContextAccessor)
|
||||
public JYApiHandler(IHttpContextAccessor? httpContextAccessor)
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
if (httpContextAccessor != null)
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -24,21 +29,7 @@ public class JYApiHandler : DelegatingHandler
|
|||
{
|
||||
try
|
||||
{
|
||||
var httpContext = _httpContextAccessor.HttpContext;
|
||||
if (httpContext == null)
|
||||
throw new InvalidOperationException("无法获取HttpContext。");
|
||||
|
||||
var host = httpContext.Request.Host.Host;
|
||||
var app = AppConfigurationExtend.GetAppConfig(host);
|
||||
if (app != null)
|
||||
{
|
||||
UpdateRequestUri(request, app.GameConfig.BsUrl);
|
||||
|
||||
if (request.Content is FormUrlEncodedContent)
|
||||
{
|
||||
await UpdateRequestContentAsync(request, app, httpContext);
|
||||
}
|
||||
}
|
||||
await SetRequest(request);
|
||||
var sw = Stopwatch.StartNew();
|
||||
var response = await base.SendAsync(request, cancellationToken);
|
||||
sw.Stop();
|
||||
|
|
@ -46,7 +37,6 @@ public class JYApiHandler : DelegatingHandler
|
|||
{
|
||||
await AttachDebugInfoAsync(request, response, sw.Elapsed.TotalMilliseconds.ToString());
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -56,10 +46,36 @@ public class JYApiHandler : DelegatingHandler
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="InvalidOperationException"></exception>
|
||||
protected virtual async Task SetRequest(HttpRequestMessage request)
|
||||
{
|
||||
var httpContext = _httpContextAccessor.HttpContext;
|
||||
if (httpContext == null)
|
||||
throw new InvalidOperationException("无法获取HttpContext。");
|
||||
|
||||
var host = httpContext.Request.Host.Host;
|
||||
var app = AppConfigurationExtend.GetAppConfig(host);
|
||||
if (app != null)
|
||||
{
|
||||
UpdateRequestUri(request, app.GameConfig.BsUrl);
|
||||
|
||||
if (request.Content is FormUrlEncodedContent)
|
||||
{
|
||||
|
||||
await UpdateRequestContentAsync(request, app, httpContext.GetClientIpAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新请求的URI
|
||||
/// </summary>
|
||||
private void UpdateRequestUri(HttpRequestMessage request, string baseUrl)
|
||||
protected void UpdateRequestUri(HttpRequestMessage request, string baseUrl)
|
||||
{
|
||||
var newUri = new Uri(new Uri(baseUrl), request.RequestUri.PathAndQuery);
|
||||
request.RequestUri = newUri;
|
||||
|
|
@ -68,12 +84,12 @@ public class JYApiHandler : DelegatingHandler
|
|||
/// <summary>
|
||||
/// 更新请求内容
|
||||
/// </summary>
|
||||
private async Task UpdateRequestContentAsync(HttpRequestMessage request, dynamic app, HttpContext httpContext)
|
||||
protected async Task UpdateRequestContentAsync(HttpRequestMessage request, AppConfig app, string ip)
|
||||
{
|
||||
var formData = await request.Content.ReadAsStringAsync();
|
||||
var parameters = ParseFormData(formData);
|
||||
|
||||
AddDefaultParameters(parameters, app, httpContext);
|
||||
AddDefaultParameters(parameters, app, ip);
|
||||
|
||||
var signKey = GenerateSignature(parameters, app.GameConfig.SignKey);
|
||||
var encryptedParameters = $"{ConvertDictionaryToPostData(parameters)}&sign={signKey}";
|
||||
|
|
@ -84,7 +100,7 @@ public class JYApiHandler : DelegatingHandler
|
|||
/// <summary>
|
||||
/// 添加默认参数
|
||||
/// </summary>
|
||||
private void AddDefaultParameters(SortedDictionary<string, object> parameters, dynamic app, HttpContext httpContext)
|
||||
protected void AddDefaultParameters(SortedDictionary<string, object> parameters, AppConfig app, string ip)
|
||||
{
|
||||
if (!parameters.ContainsKey("channel_id"))
|
||||
{
|
||||
|
|
@ -93,7 +109,7 @@ public class JYApiHandler : DelegatingHandler
|
|||
|
||||
if (!parameters.ContainsKey("ip"))
|
||||
{
|
||||
parameters["ip"] = httpContext.GetClientIpAddress();
|
||||
parameters["ip"] = ip;
|
||||
}
|
||||
|
||||
if (!parameters.ContainsKey("time"))
|
||||
|
|
@ -105,7 +121,7 @@ public class JYApiHandler : DelegatingHandler
|
|||
/// <summary>
|
||||
/// 生成签名
|
||||
/// </summary>
|
||||
private string GenerateSignature(SortedDictionary<string, object> parameters, string signKey)
|
||||
protected string GenerateSignature(SortedDictionary<string, object> parameters, string signKey)
|
||||
{
|
||||
var dataString = string.Join("&", parameters.Select(kv => $"{kv.Key}={kv.Value}")) + $"&key={signKey}";
|
||||
return MD5Encryption.ComputeMD5Hash(dataString).ToUpper();
|
||||
|
|
@ -114,7 +130,7 @@ public class JYApiHandler : DelegatingHandler
|
|||
/// <summary>
|
||||
/// 附加调试信息到响应
|
||||
/// </summary>
|
||||
private async Task AttachDebugInfoAsync(HttpRequestMessage request, HttpResponseMessage response, string totalMilliseconds)
|
||||
protected async Task AttachDebugInfoAsync(HttpRequestMessage request, HttpResponseMessage response, string totalMilliseconds)
|
||||
{
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
var responseJson = JsonConvert.DeserializeObject<JObject>(responseContent);
|
||||
|
|
@ -131,7 +147,7 @@ public class JYApiHandler : DelegatingHandler
|
|||
/// <summary>
|
||||
/// 序列化HTTP响应
|
||||
/// </summary>
|
||||
private string SerializeResponse(HttpResponseMessage response, string content)
|
||||
protected string SerializeResponse(HttpResponseMessage response, string content)
|
||||
{
|
||||
return JsonConvert.SerializeObject(new
|
||||
{
|
||||
|
|
@ -144,7 +160,7 @@ public class JYApiHandler : DelegatingHandler
|
|||
/// <summary>
|
||||
/// 解析表单数据
|
||||
/// </summary>
|
||||
private SortedDictionary<string, object> ParseFormData(string formData)
|
||||
protected SortedDictionary<string, object> ParseFormData(string formData)
|
||||
{
|
||||
var parameters = new SortedDictionary<string, object>();
|
||||
var pairs = formData.Split('&');
|
||||
|
|
@ -164,7 +180,7 @@ public class JYApiHandler : DelegatingHandler
|
|||
/// <summary>
|
||||
/// 将字典转换为POST数据格式
|
||||
/// </summary>
|
||||
private string ConvertDictionaryToPostData(SortedDictionary<string, object> dictionary)
|
||||
protected string ConvertDictionaryToPostData(SortedDictionary<string, object> dictionary)
|
||||
{
|
||||
return string.Join("&", dictionary.Select(kv => $"{kv.Key}={kv.Value}"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,5 +25,21 @@ namespace CloudGaming.AppConfigModel
|
|||
/// 客户渠道地址
|
||||
/// </summary>
|
||||
public string BsUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户多少秒后可以重连会话,必须小于结束游戏前
|
||||
/// </summary>
|
||||
public int UserReconnectTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户没有心跳后多少秒判断掉线
|
||||
/// </summary>
|
||||
public int UserNotActionDisconnect { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 用户没有心跳后多少秒结束游戏
|
||||
/// </summary>
|
||||
public int UserNotActionEndGame { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using CloudGaming.DtoModel.JY;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
|
@ -10,11 +12,15 @@ namespace CloudGaming.DtoModel.PlayGame
|
|||
/// <summary>
|
||||
/// 切换视频
|
||||
/// </summary>
|
||||
public class DisplayGradeSettings : PlayGameCommonSetting
|
||||
public class DisplayGradeSettings : JYRequestParameter// PlayGameCommonSetting
|
||||
{
|
||||
public DisplayGradeSettings() { }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 本次游戏连接会话 id
|
||||
/// </summary>
|
||||
[JsonPropertyName("sc_id")]
|
||||
public int ScId { get; set; }
|
||||
/// <summary>
|
||||
/// 显示等级,可在后台配置,默认为 1
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -141,6 +141,11 @@ public class PlayGameUserInfo
|
|||
/// </summary>
|
||||
public int DiamondListId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ip地址
|
||||
/// </summary>
|
||||
public string Ip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 转化成数据库实体类
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CloudGaming.DtoModel.PlayGame;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 重连会话
|
||||
/// </summary>
|
||||
public class ReconPlayGameRequest : PlayGameCommonSetting
|
||||
{
|
||||
public ReconPlayGameRequest() { }
|
||||
|
||||
/// <summary>
|
||||
/// 显示等级,可在后台配置,默认为 1
|
||||
/// </summary>
|
||||
[JsonPropertyName("display_grade")]
|
||||
public int? DisplayGrade { get; set; } = 1; // 默认值为 1
|
||||
|
||||
/// <summary>
|
||||
/// 设备型号
|
||||
/// </summary>
|
||||
[JsonPropertyName("model_name")]
|
||||
public string ModelName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 芯片
|
||||
/// </summary>
|
||||
[JsonPropertyName("cpu")]
|
||||
public string Cpu { get; set; }
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
using CloudGaming.DtoModel.JY;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
|
@ -10,13 +12,17 @@ namespace CloudGaming.DtoModel.PlayGame
|
|||
/// <summary>
|
||||
/// 重连会话
|
||||
/// </summary>
|
||||
public class ReconPlayGameSettings : PlayGameCommonSetting
|
||||
public class ReconPlayGameSettings : JYRequestParameter// PlayGameCommonSetting
|
||||
{
|
||||
public ReconPlayGameSettings() { }
|
||||
|
||||
public ReconPlayGameSettings(string sn, int userId) : base(sn, userId)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 会话 id
|
||||
/// 本次游戏连接会话 id
|
||||
/// </summary>
|
||||
[JsonPropertyName("sc_id")]
|
||||
public int ScId { get; set; }
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user