0
0
mirror of https://github.com/sp-tarkov/modules.git synced 2025-02-13 09:50:43 -05:00
modules/project/Aki.SinglePlayer/Patches/RaidFix/GetNewBotTemplatesPatch.cs

106 lines
4.3 KiB
C#
Raw Normal View History

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;
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()
{
var desiredType = typeof(BotsPresets);
_getNewProfileMethod = desiredType
.GetMethod(nameof(BotsPresets.GetNewProfile), BindingFlags.Instance | BindingFlags.NonPublic); // want the func with 2 params (protected + inherited from base)
Logger.LogDebug($"{this.GetType().Name} Type: {desiredType?.Name}");
Logger.LogDebug($"{this.GetType().Name} Method: {_getNewProfileMethod?.Name}");
2023-03-03 18:52:31 +00: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
}
/// <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
{
/*
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)
{
Logger.LogDebug($"GetNewBotTemplatesPatch() getNewProfile() failed: {e.Message} {e.InnerException}");
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
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;
}
}
}