2023-03-03 18:52:31 +00:00
using System.Linq ;
using System.Reflection ;
using System.Threading.Tasks ;
using EFT ;
using Aki.Reflection.Patching ;
using Aki.Reflection.Utils ;
using Aki.SinglePlayer.Models.RaidFix ;
2023-06-25 13:49:48 +01:00
using System ;
2023-07-12 16:54:53 +01:00
using System.Collections.Generic ;
2023-03-03 18:52:31 +00:00
namespace Aki.SinglePlayer.Patches.RaidFix
{
public class GetNewBotTemplatesPatch : ModulePatch
{
private static MethodInfo _getNewProfileMethod ;
static GetNewBotTemplatesPatch ( )
{
_ = nameof ( IBotData . PrepareToLoadBackend ) ;
_ = nameof ( BotsPresets . GetNewProfile ) ;
_ = nameof ( PoolManager . LoadBundlesAndCreatePools ) ;
_ = nameof ( JobPriority . General ) ;
}
2023-07-30 09:47:25 +01:00
/// <summary>
/// BotsPresets.GetNewProfile()
/// </summary>
2023-03-03 18:52:31 +00:00
public GetNewBotTemplatesPatch ( )
{
2023-07-07 16:15:22 +01:00
var desiredType = typeof ( BotsPresets ) ;
_getNewProfileMethod = desiredType
2023-07-09 14:51:13 +01:00
. GetMethod ( nameof ( BotsPresets . GetNewProfile ) , BindingFlags . Instance | BindingFlags . NonPublic ) ; // want the func with 2 params (protected + inherited from base)
2023-07-07 16:15:22 +01:00
Logger . LogDebug ( $"{this.GetType().Name} Type: {desiredType?.Name}" ) ;
Logger . LogDebug ( $"{this.GetType().Name} Method: {_getNewProfileMethod?.Name}" ) ;
2023-03-03 18:52:31 +00:00
}
2023-07-09 14:51:13 +01:00
/// <summary>
/// Looking for CreateProfile()
/// </summary>
/// <returns></returns>
2023-03-03 18:52:31 +00:00
protected override MethodBase GetTargetMethod ( )
{
return typeof ( BotsPresets ) . GetMethods ( BindingFlags . Public | BindingFlags . Instance | BindingFlags . DeclaredOnly )
. Single ( x = > IsTargetMethod ( x ) ) ;
}
private bool IsTargetMethod ( MethodInfo mi )
{
var parameters = mi . GetParameters ( ) ;
2023-07-07 15:01:45 +01:00
return ( parameters . Length = = 3
2023-03-03 18:52:31 +00:00
& & parameters [ 0 ] . Name = = "data"
2023-07-07 15:01:45 +01:00
& & parameters [ 1 ] . Name = = "cancellationToken"
& & parameters [ 2 ] . Name = = "withDelete" ) ;
2023-03-03 18:52:31 +00:00
}
2023-07-12 16:54:53 +01:00
/// <summary>
/// BotsPresets.GetNewProfile()
/// </summary>
2023-03-03 18:52:31 +00:00
[PatchPrefix]
2023-07-28 10:01:11 +01:00
private static bool PatchPrefix ( ref Task < Profile > __result , BotsPresets __instance , List < Profile > ___list_0 , GClass628 data , ref bool withDelete )
2023-03-03 18:52:31 +00:00
{
2023-07-12 16:54:53 +01:00
/ *
When client wants new bot and GetNewProfile ( ) return null ( if not more available templates or they don ' t satisfy by Role and Difficulty condition )
then client gets new piece of WaveInfo collection ( with Limit = 30 by default ) and make request to server
but use only first value in response ( this creates a lot of garbage and cause freezes )
after patch we request only 1 template from server along with other patches this one causes to call data . PrepareToLoadBackend ( 1 ) gets the result with required role and difficulty :
new [ ] { new WaveInfo ( ) { Limit = 1 , Role = role , Difficulty = difficulty } }
then perform request to server and get only first value of resulting single element collection
* /
try
{
// Force true to ensure bot profile is deleted after use
_getNewProfileMethod . Invoke ( __instance , new object [ ] { data , true } ) ;
}
catch ( Exception e )
{
2023-07-12 17:36:10 +01:00
Logger . LogDebug ( $"GetNewBotTemplatesPatch() getNewProfile() failed: {e.Message} {e.InnerException}" ) ;
2023-07-12 16:54:53 +01:00
throw ;
}
// Load from server
var source = data . PrepareToLoadBackend ( 1 ) . Take ( 1 ) . ToList ( ) ;
var taskScheduler = TaskScheduler . FromCurrentSynchronizationContext ( ) ;
var taskAwaiter = ( Task < Profile > ) null ;
taskAwaiter = PatchConstants . BackEndSession . LoadBots ( source ) . ContinueWith ( GetFirstResult , taskScheduler ) ;
// Load bundles for bot profile
var continuation = new BundleLoader ( taskScheduler ) ;
__result = taskAwaiter . ContinueWith ( continuation . LoadBundles , taskScheduler ) . Unwrap ( ) ;
2023-03-03 18:52:31 +00:00
2023-07-12 16:54:53 +01:00
return false ;
2023-03-03 18:52:31 +00:00
}
private static Profile GetFirstResult ( Task < Profile [ ] > task )
{
var result = task . Result [ 0 ] ;
2023-07-30 09:47:25 +01:00
Logger . LogInfo ( $"{DateTime.Now:T} Loading bot: {result.Info.Nickname} profile from server. Role: {result.Info.Settings.Role} Side: {result.Side}" ) ;
2023-06-25 13:49:48 +01:00
2023-03-03 18:52:31 +00:00
return result ;
}
}
}