using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using HarmonyLib;
using NitroxClient.GameLogic.Spawning;
using NitroxClient.GameLogic.Spawning.Metadata.Processor;
using NitroxClient.Helpers;
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
using NitroxModel.Helper;
using UnityEngine;
namespace NitroxPatcher.Patches.Dynamic;
///
/// Applies metadata to a spawned GrownPlant when it was provided by
///
public sealed partial class GrowingPlant_SpawnGrownModelAsync_Patch : NitroxPatch, IDynamicPatch
{
internal static readonly MethodInfo TARGET_METHOD = AccessTools.EnumeratorMoveNext(Reflect.Method((GrowingPlant t) => t.SpawnGrownModelAsync()));
/*
* REPLACE:
* grownPlant.SendMessage("OnGrown", SendMessageOptions.DontRequireReceiver);
* BY:
* GrowingPlant_SpawnGrownModelAsync_Patch.OnGrown(grownPlant, this);
*/
public static IEnumerable Transpiler(IEnumerable instructions)
{
return new CodeMatcher(instructions).MatchStartForward([
new CodeMatch(OpCodes.Ldstr, "OnGrown"),
new CodeMatch(OpCodes.Ldc_I4_1),
new CodeMatch(OpCodes.Callvirt)
])
.RemoveInstructions(3) // Remove the Ldstr, Ldc_I4_1 and callvirt
.Insert([ // GrownPlant component is already on stack
new CodeInstruction(OpCodes.Ldloc_1), // Ldloc_1 refers to this instance (GrowingPlant)
new CodeInstruction(OpCodes.Call, Reflect.Method(() => OnGrown(default, default)))
])
.InstructionEnumeration();
}
public static void OnGrown(GrownPlant grownPlant, GrowingPlant growingPlant)
{
if (!grownPlant.TryGetComponent(out FruitPlant fruitPlant) || !growingPlant.TryGetReference(out FruitPlantMetadata fruitPlantMetadata))
{
// Original call if we don't need to apply anything
grownPlant.SendMessage("OnGrown", SendMessageOptions.DontRequireReceiver);
return;
}
// Only useful stuff from FruitPlant.OnGrown
fruitPlant.Initialize();
fruitPlant.fruitSpawnEnabled = true;
Resolve().ProcessMetadata(grownPlant.seed.gameObject, fruitPlantMetadata);
}
}