Further 2.3.0 work

This commit is contained in:
Chomp 2022-03-21 15:30:58 +00:00
parent cdb3f6d370
commit 4ec6a912ce
6 changed files with 90 additions and 32 deletions

View File

@ -16,7 +16,8 @@ namespace astealz.SmartSpawnController.Patches
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
return botSpawnerType.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) return botSpawnerType
.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Single(); .Single();
} }

View File

@ -8,7 +8,7 @@ namespace astealz.SmartSpawnController.Patches
{ {
class MaxBotsAliveOnMapPatch : GenericPatch<MaxBotsAliveOnMapPatch> class MaxBotsAliveOnMapPatch : GenericPatch<MaxBotsAliveOnMapPatch>
{ {
private static string[] targetTypePublicProperties = new string[] { "BotsCountWithDelyaed", "AllTypes", "IsEnable" }; private static string[] targetTypePublicProperties = new string[] { "BotsCountWithDelayed", "AllTypes", "IsEnable" };
public MaxBotsAliveOnMapPatch() : base(prefix: nameof(PatchPrefix)) public MaxBotsAliveOnMapPatch() : base(prefix: nameof(PatchPrefix))
{ {
@ -17,9 +17,7 @@ namespace astealz.SmartSpawnController.Patches
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
// searching type with properties: BotsCountWithDelyaed, AllTypes, AiTaskManager // searching type with properties: BotsCountWithDelyaed, AllTypes, AiTaskManager
return typeof(EFT.GameWorld).Assembly.GetTypes() return typeof(BotControllerClass).GetMethod("SetSettings");
.Single(type => targetTypePublicProperties.All(p => type.GetProperties(allFlags).Any(tp => tp.Name == p)))
.GetMethod("SetSettings");
} }
private static void PatchPrefix(ref int maxCount) private static void PatchPrefix(ref int maxCount)

View File

@ -1,12 +1,14 @@
using System; using BepInEx.Logging;
using System;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
namespace astealz.SmartSpawnController.Patches namespace astealz.SmartSpawnController.Patches
{ {
partial class BotSpawnerPatches static partial class BotSpawnerPatches
{ {
const BindingFlags allFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; const BindingFlags allFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
const BindingFlags publicInstanceDeclared = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
private static readonly Type scavWaveDataType; private static readonly Type scavWaveDataType;
private static readonly Type botSpawnerType; private static readonly Type botSpawnerType;
@ -18,6 +20,8 @@ namespace astealz.SmartSpawnController.Patches
// ctor // ctor
static BotSpawnerPatches() static BotSpawnerPatches()
{ {
var logSource = Logger.CreateLogSource("test");
var scavWaveDataTypeFieldNames = new[] var scavWaveDataTypeFieldNames = new[]
{ {
"ChanceGroup", "ChanceGroup",
@ -31,32 +35,72 @@ namespace astealz.SmartSpawnController.Patches
}; };
var types = typeof(EFT.GameWorld).Assembly.GetTypes(); var types = typeof(EFT.GameWorld).Assembly.GetTypes();
var botControllerClass = types.Single(x => x.Name == "BotControllerClass");
scavWaveDataType = types if (botControllerClass is null)
.Where(type => type != typeof(EFT.WildSpawnWave)) {
.Where(type => type.GetFields(BindingFlags.Public | BindingFlags.Instance) logSource.LogInfo($"botcontroller null");
.Select(x => x.Name) }
.DefaultIfEmpty("")
.All(scavWaveDataTypeFieldNames.Contains))
.Single();
botSpawnerType = types var activateBotsByWaveMethod = botControllerClass.GetMethods().Single(x => x.Name == "ActivateBotsByWave" && x.GetParameters()[0].ParameterType != typeof(BossLocationSpawn));
.Where(type => type.GetMethod("SpawnZones", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) != null var firstParam = activateBotsByWaveMethod.GetParameters()[0];
&& type.GetMethod("ActivateBotsByWave", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, new[] { scavWaveDataType }, null) != null) scavWaveDataType = firstParam.ParameterType;
.SingleOrDefault(); botSpawnerType = types.Single(x => x.Name == "GClass1243");
if (botSpawnerType is null)
{
logSource.LogInfo($"botSpawnerType is null");
}
//var dataTypes = types
// .Where(type => type != typeof(EFT.WildSpawnWave) && type.GetFields(BindingFlags.Public | BindingFlags.Instance)
// .Select(x => x.Name)
// .DefaultIfEmpty("")
// .All(scavWaveDataTypeFieldNames.Contains));
//var typesFound = dataTypes.Where(type => type.GetMethod("SpawnZones", publicInstanceDeclared) != null
// && type.GetMethod("ActivateBotsByWave", publicInstanceDeclared, null, new[] { scavWaveDataType }, null) != null);
//foreach (var item in typesFound)
//{
// logSource.LogInfo($"WOW found: {item.Name}");
//}
//scavWaveDataType = dataTypes.Single();
//if (scavWaveDataType is null)
//{
// logSource.LogError("scavWaveDataType is null");
//}
//botSpawnerType = types.Single(type => type.GetMethod("SpawnZones", publicInstanceDeclared) != null
// && type.GetMethod("ActivateBotsByWave", publicInstanceDeclared, null, new[] { scavWaveDataType }, null) != null);
//if (botSpawnerType is null)
//{
// logSource.LogError("botSpawnerType is null");
//}
} }
/// <summary> /// <summary>
/// Apply patches /// Apply patches
/// </summary> /// </summary>
public static bool Apply() public static bool ApplyAllPatches(BepInEx.Logging.ManualLogSource logger)
{ {
logger.LogInfo($"MaxBotsAliveOnMapPatch");
new MaxBotsAliveOnMapPatch().Apply(); new MaxBotsAliveOnMapPatch().Apply();
logger.LogInfo($"BotSpawnerOnStartPatch");
new BotSpawnerOnStartPatch().Apply(); new BotSpawnerOnStartPatch().Apply();
logger.LogInfo($"BotSpawnerOnActivateBotsByScavWavePatch");
new BotSpawnerOnActivateBotsByScavWavePatch().Apply(); new BotSpawnerOnActivateBotsByScavWavePatch().Apply();
logger.LogInfo($"BotSpawnerOnActivateBotsByBossWavePatch");
new BotSpawnerOnActivateBotsByBossWavePatch().Apply(); new BotSpawnerOnActivateBotsByBossWavePatch().Apply();
logger.LogInfo($"BotSpawnerOnStopPatch");
new BotSpawnerOnStopPatch().Apply(); new BotSpawnerOnStopPatch().Apply();
logger.LogInfo($"BotSpawnerDelayPatch");
new BotSpawnerDelayPatch().Apply(); new BotSpawnerDelayPatch().Apply();
logger.LogInfo($"BotSpawnerOnBossActivationPatch");
new BotSpawnerOnBossActivationPatch().Apply(); new BotSpawnerOnBossActivationPatch().Apply();
return true; return true;
} }

View File

@ -1,4 +1,5 @@
using BepInEx; using astealz.SmartSpawnController.Patches;
using BepInEx;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
@ -21,16 +22,20 @@ namespace astealz.SmartSpawnController
// get config from server // get config from server
var json = Aki.SinglePlayer.Utils.RequestHandler.GetJson($"/mods/{Name.ToLower()}/config"); var json = Aki.SinglePlayer.Utils.RequestHandler.GetJson($"/mods/{Name.ToLower()}/config");
var config = JsonConvert.DeserializeObject<Config>(json); Globals.Config = JsonConvert.DeserializeObject<Config>(json);
Globals.Config = config;
// apply patches // apply patches
isApplyPatchesSuccess = Patches.BotSpawnerPatches.Apply(); Logger.LogInfo("appying patches");
if (!isApplyPatchesSuccess)
{
isApplyPatchesSuccess = BotSpawnerPatches.ApplyAllPatches(Logger);
}
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.LogError(ex.ToString()); Logger.LogError($"Start failed: {ex.Message}");
Logger.LogError($"Start failed: {ex.StackTrace}");
} }
} }

View File

@ -6,11 +6,11 @@ namespace astealz.SmartSpawnController.Utils
{ {
public abstract class GenericPatch<T> where T : GenericPatch<T> public abstract class GenericPatch<T> where T : GenericPatch<T>
{ {
private Harmony _harmony; private readonly Harmony _harmony;
private HarmonyMethod _prefix; private readonly HarmonyMethod _prefix;
private HarmonyMethod _postfix; private readonly HarmonyMethod _postfix;
private HarmonyMethod _transpiler; private readonly HarmonyMethod _transpiler;
private HarmonyMethod _finalizer; private readonly HarmonyMethod _finalizer;
public GenericPatch(string name = null, string prefix = null, string postfix = null, string transpiler = null, string finalizer = null) public GenericPatch(string name = null, string prefix = null, string postfix = null, string transpiler = null, string finalizer = null)
{ {
@ -52,7 +52,17 @@ namespace astealz.SmartSpawnController.Utils
/// </summary> /// </summary>
public void Apply() public void Apply()
{ {
var targetMethod = GetTargetMethod(); MethodBase targetMethod;
try
{
targetMethod = GetTargetMethod();
}
catch (Exception ex)
{
throw new Exception($"targetMethod bad: {typeof(T).Name}:", ex);
}
if (targetMethod == null) if (targetMethod == null)
{ {
@ -65,7 +75,7 @@ namespace astealz.SmartSpawnController.Utils
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new Exception($"{_harmony.Id}:", ex); throw new Exception($"{typeof(T).Name}:{_harmony.Id}:", ex);
} }
} }