Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
3015237661 | |||
c6576c0e11 | |||
1bdddc3dc5 | |||
1aae2f194c |
@ -1,308 +1,105 @@
|
||||
using EFT.Interactive;
|
||||
using Comfort.Common;
|
||||
using EFT;
|
||||
using EFT.Interactive;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Aki.Custom.Airdrops.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SamSWAT.HeliCrash
|
||||
{
|
||||
public class HeliCrash : MonoBehaviour
|
||||
{
|
||||
private AssetBundle UH60Bundle;
|
||||
private GameObject Choppa;
|
||||
private Location HeliLocation;
|
||||
private LootableContainer ChoppaContainer;
|
||||
private string playerlocation;
|
||||
//public GameObject fpscamera;
|
||||
//private int counter = 0;
|
||||
private AssetBundle _heliBundle;
|
||||
|
||||
public async void Init(string location)
|
||||
{
|
||||
playerlocation = location;
|
||||
string path = Plugin.Directory + "Assets/Content/Vehicles/sikorsky_uh60_blackhawk.bundle";
|
||||
var heliLocation = GetHeliCrashLocation(location);
|
||||
var choppa = Instantiate(await LoadChoppaAsync(), heliLocation.Position, Quaternion.Euler(heliLocation.Rotation));
|
||||
var container = choppa.GetComponentInChildren<LootableContainer>();
|
||||
|
||||
var itemCrate = Utils.CreateItem("goofyahcontainer", "6223349b3136504a544d1608");
|
||||
LootItem.CreateLootContainer(container, itemCrate, "Heavy crate", Singleton<GameWorld>.Instance);
|
||||
|
||||
new ItemFactoryUtil().AddLoot(container);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
_heliBundle.Unload(true);
|
||||
}
|
||||
|
||||
private Location GetHeliCrashLocation(string location)
|
||||
{
|
||||
switch (location)
|
||||
{
|
||||
case "bigmap":
|
||||
{
|
||||
return Plugin.HeliCrashLocations.Customs.Shuffle().SelectRandom();
|
||||
}
|
||||
case "Interchange":
|
||||
{
|
||||
return Plugin.HeliCrashLocations.Interchange.Shuffle().SelectRandom();;
|
||||
}
|
||||
case "RezervBase":
|
||||
{
|
||||
return Plugin.HeliCrashLocations.Rezerv.Shuffle().SelectRandom();;
|
||||
}
|
||||
case "Shoreline":
|
||||
{
|
||||
return Plugin.HeliCrashLocations.Shoreline.Shuffle().SelectRandom();;
|
||||
}
|
||||
case "Woods":
|
||||
{
|
||||
return Plugin.HeliCrashLocations.Woods.Shuffle().SelectRandom();;
|
||||
}
|
||||
case "Lighthouse":
|
||||
{
|
||||
return Plugin.HeliCrashLocations.Lighthouse.Shuffle().SelectRandom();;
|
||||
}
|
||||
case "TarkovStreets":
|
||||
{
|
||||
return Plugin.HeliCrashLocations.StreetsOfTarkov.Shuffle().SelectRandom();;
|
||||
}
|
||||
case "develop":
|
||||
{
|
||||
return Plugin.HeliCrashLocations.Develop.Shuffle().SelectRandom();;
|
||||
}
|
||||
default: return new Location();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<GameObject> LoadChoppaAsync()
|
||||
{
|
||||
var path = $"{Plugin.Directory}/Assets/Content/Vehicles/sikorsky_uh60_blackhawk.bundle";
|
||||
|
||||
var bundleLoadRequest = AssetBundle.LoadFromFileAsync(path);
|
||||
|
||||
while (!bundleLoadRequest.isDone)
|
||||
await Task.Yield();
|
||||
|
||||
UH60Bundle = bundleLoadRequest.assetBundle;
|
||||
_heliBundle = bundleLoadRequest.assetBundle;
|
||||
|
||||
if (UH60Bundle == null)
|
||||
if (_heliBundle == null)
|
||||
{
|
||||
Plugin.LogSource.LogFatal("Can't load UH-60 Blackhawk bundle");
|
||||
Debug.LogError("[SamSWAT.HeliCrash]: Can't load UH-60 Blackhawk bundle");
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
var assetLoadRequest = UH60Bundle.LoadAllAssetsAsync<GameObject>();
|
||||
var assetLoadRequest = _heliBundle.LoadAllAssetsAsync<GameObject>();
|
||||
|
||||
while (!assetLoadRequest.isDone)
|
||||
await Task.Yield();
|
||||
|
||||
Choppa = assetLoadRequest.allAssets[0] as GameObject;
|
||||
var requestedGo = assetLoadRequest.allAssets[0] as GameObject;
|
||||
|
||||
if (Choppa == null)
|
||||
{
|
||||
Debug.LogError("[SamSWAT.HeliCrash]: failed to load asset");
|
||||
return;
|
||||
}
|
||||
if (requestedGo != null) return requestedGo;
|
||||
|
||||
Plugin.LogSource.LogFatal("Failed to load heli asset");
|
||||
Debug.LogError("[SamSWAT.HeliCrash]: failed to load heli asset");
|
||||
return null;
|
||||
|
||||
HeliLocation = HeliCrashLocation();
|
||||
Choppa = Instantiate(Choppa, HeliLocation.Position, Quaternion.Euler(HeliLocation.Rotation));
|
||||
UH60Bundle.Unload(false);
|
||||
|
||||
ChoppaContainer = Choppa.GetComponentInChildren<LootableContainer>();
|
||||
var airdropsyncobjects = LocationScene.GetAll<SynchronizableObject>().Where(x => x.GetComponent<AirdropSynchronizableObject>());
|
||||
var airdropcrates = new List<LootableContainer>();
|
||||
|
||||
foreach(var crate in airdropsyncobjects)
|
||||
{
|
||||
airdropcrates.Add(crate.GetComponentInChildren<LootableContainer>());
|
||||
}
|
||||
|
||||
FieldInfo itemOwner = typeof(LootableContainer).GetField("ItemOwner");
|
||||
object items = itemOwner.GetValue(PickRandom(airdropcrates));
|
||||
itemOwner.SetValue(ChoppaContainer, items);
|
||||
//fpscamera = GameObject.Find("FPS Camera");
|
||||
}
|
||||
|
||||
private Location HeliCrashLocation()
|
||||
{
|
||||
switch (playerlocation)
|
||||
{
|
||||
case "bigmap":
|
||||
{
|
||||
return PickRandom(Plugin.HeliCrashLocations.Customs);
|
||||
}
|
||||
case "Interchange":
|
||||
{
|
||||
return PickRandom(Plugin.HeliCrashLocations.Interchange);
|
||||
}
|
||||
case "RezervBase":
|
||||
{
|
||||
return PickRandom(Plugin.HeliCrashLocations.Rezerv);
|
||||
}
|
||||
case "Shoreline":
|
||||
{
|
||||
return PickRandom(Plugin.HeliCrashLocations.Shoreline);
|
||||
}
|
||||
case "Woods":
|
||||
{
|
||||
return PickRandom(Plugin.HeliCrashLocations.Woods);
|
||||
}
|
||||
case "Lighthouse":
|
||||
{
|
||||
return PickRandom(Plugin.HeliCrashLocations.Lighthouse);
|
||||
}
|
||||
case "develop":
|
||||
{
|
||||
return PickRandom(Plugin.HeliCrashLocations.Develop);
|
||||
}
|
||||
default: return new Location();
|
||||
}
|
||||
}
|
||||
|
||||
private T PickRandom<T>(List<T> list)
|
||||
{
|
||||
return list[Random.Range(0, list.Count)];
|
||||
}
|
||||
|
||||
/* private void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.Keypad5))
|
||||
{
|
||||
var cumpos = fpscamera.transform.position;
|
||||
var cumrot = fpscamera.transform.eulerAngles;
|
||||
Physics.Raycast(cumpos, Vector3.down, out var raycastHit, 50f);
|
||||
Choppa.transform.position = new Vector3(cumpos.x, raycastHit.point.y - 0.12f, cumpos.z);
|
||||
Choppa.transform.eulerAngles = new Vector3(0, cumrot.y, 0);
|
||||
}
|
||||
if (Input.GetKeyDown(KeyCode.Keypad6))
|
||||
{
|
||||
switch (playerlocation)
|
||||
{
|
||||
case "bigmap":
|
||||
{
|
||||
Plugin.heliCrashSites.Customs.Add(new Location { Position = Choppa.transform.position, Rotation = Choppa.transform.rotation.eulerAngles });
|
||||
break;
|
||||
}
|
||||
case "Interchange":
|
||||
{
|
||||
Plugin.heliCrashSites.Interchange.Add(new Location { Position = Choppa.transform.position, Rotation = Choppa.transform.rotation.eulerAngles });
|
||||
break;
|
||||
}
|
||||
case "RezervBase":
|
||||
{
|
||||
Plugin.heliCrashSites.Rezerv.Add(new Location { Position = Choppa.transform.position, Rotation = Choppa.transform.rotation.eulerAngles });
|
||||
break;
|
||||
}
|
||||
case "Shoreline":
|
||||
{
|
||||
Plugin.heliCrashSites.Shoreline.Add(new Location { Position = Choppa.transform.position, Rotation = Choppa.transform.rotation.eulerAngles });
|
||||
break;
|
||||
}
|
||||
case "Woods":
|
||||
{
|
||||
Plugin.heliCrashSites.Woods.Add(new Location { Position = Choppa.transform.position, Rotation = Choppa.transform.rotation.eulerAngles });
|
||||
break;
|
||||
}
|
||||
case "Lighthouse":
|
||||
{
|
||||
Plugin.heliCrashSites.Lighthouse.Add(new Location { Position = Choppa.transform.position, Rotation = Choppa.transform.rotation.eulerAngles });
|
||||
break;
|
||||
}
|
||||
case "develop":
|
||||
{
|
||||
Plugin.heliCrashSites.Develop.Add(new Location { Position = Choppa.transform.position, Rotation = Choppa.transform.rotation.eulerAngles });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Input.GetKeyDown(KeyCode.Keypad0))
|
||||
{
|
||||
File.WriteAllText(Plugin.Directory + "HeliCrashLocations.json", JsonConvert.SerializeObject(Plugin.heliCrashSites));
|
||||
Debug.LogError("Data has been saved to file");
|
||||
}
|
||||
if (Input.GetKeyDown(KeyCode.Keypad8))
|
||||
{
|
||||
switch (playerlocation)
|
||||
{
|
||||
case "bigmap":
|
||||
{
|
||||
if (counter < Plugin.heliCrashSites.Customs.Count)
|
||||
{
|
||||
var loca = Plugin.heliCrashSites.Customs[counter];
|
||||
Choppa.transform.position = loca.Position;
|
||||
Choppa.transform.eulerAngles = loca.Rotation;
|
||||
counter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
counter = 0;
|
||||
var loca = Plugin.heliCrashSites.Customs[counter];
|
||||
Choppa.transform.position = loca.Position;
|
||||
Choppa.transform.eulerAngles = loca.Rotation;
|
||||
counter++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "Interchange":
|
||||
{
|
||||
if (counter < Plugin.heliCrashSites.Interchange.Count)
|
||||
{
|
||||
var loca = Plugin.heliCrashSites.Interchange[counter];
|
||||
Choppa.transform.position = loca.Position;
|
||||
Choppa.transform.eulerAngles = loca.Rotation;
|
||||
counter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
counter = 0;
|
||||
var loca = Plugin.heliCrashSites.Interchange[counter];
|
||||
Choppa.transform.position = loca.Position;
|
||||
Choppa.transform.eulerAngles = loca.Rotation;
|
||||
counter++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "RezervBase":
|
||||
{
|
||||
if (counter < Plugin.heliCrashSites.Rezerv.Count)
|
||||
{
|
||||
var loca = Plugin.heliCrashSites.Rezerv[counter];
|
||||
Choppa.transform.position = loca.Position;
|
||||
Choppa.transform.eulerAngles = loca.Rotation;
|
||||
counter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
counter = 0;
|
||||
var loca = Plugin.heliCrashSites.Rezerv[counter];
|
||||
Choppa.transform.position = loca.Position;
|
||||
Choppa.transform.eulerAngles = loca.Rotation;
|
||||
counter++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "Shoreline":
|
||||
{
|
||||
if (counter < Plugin.heliCrashSites.Shoreline.Count)
|
||||
{
|
||||
var loca = Plugin.heliCrashSites.Shoreline[counter];
|
||||
Choppa.transform.position = loca.Position;
|
||||
Choppa.transform.eulerAngles = loca.Rotation;
|
||||
counter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
counter = 0;
|
||||
var loca = Plugin.heliCrashSites.Shoreline[counter];
|
||||
Choppa.transform.position = loca.Position;
|
||||
Choppa.transform.eulerAngles = loca.Rotation;
|
||||
counter++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "Woods":
|
||||
{
|
||||
if (counter < Plugin.heliCrashSites.Woods.Count)
|
||||
{
|
||||
var loca = Plugin.heliCrashSites.Woods[counter];
|
||||
Choppa.transform.position = loca.Position;
|
||||
Choppa.transform.eulerAngles = loca.Rotation;
|
||||
counter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
counter = 0;
|
||||
var loca = Plugin.heliCrashSites.Woods[counter];
|
||||
Choppa.transform.position = loca.Position;
|
||||
Choppa.transform.eulerAngles = loca.Rotation;
|
||||
counter++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "Lighthouse":
|
||||
{
|
||||
if (counter < Plugin.heliCrashSites.Lighthouse.Count)
|
||||
{
|
||||
var loca = Plugin.heliCrashSites.Lighthouse[counter];
|
||||
Choppa.transform.position = loca.Position;
|
||||
Choppa.transform.eulerAngles = loca.Rotation;
|
||||
counter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
counter = 0;
|
||||
var loca = Plugin.heliCrashSites.Lighthouse[counter];
|
||||
Choppa.transform.position = loca.Position;
|
||||
Choppa.transform.eulerAngles = loca.Rotation;
|
||||
counter++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "develop":
|
||||
{
|
||||
if (counter < Plugin.heliCrashSites.Develop.Count)
|
||||
{
|
||||
var loca = Plugin.heliCrashSites.Develop[counter];
|
||||
Choppa.transform.position = loca.Position;
|
||||
Choppa.transform.eulerAngles = loca.Rotation;
|
||||
counter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
counter = 0;
|
||||
var loca = Plugin.heliCrashSites.Develop[counter];
|
||||
Choppa.transform.position = loca.Position;
|
||||
Choppa.transform.eulerAngles = loca.Rotation;
|
||||
counter++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
using Aki.Reflection.Patching;
|
||||
using Aki.Reflection.Utils;
|
||||
using Comfort.Common;
|
||||
using EFT;
|
||||
using EFT.Airdrop;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
@ -11,26 +13,21 @@ namespace SamSWAT.HeliCrash
|
||||
{
|
||||
protected override MethodBase GetTargetMethod()
|
||||
{
|
||||
return typeof(GameWorld).GetMethod("OnGameStarted", BindingFlags.Public | BindingFlags.Instance);
|
||||
//return PatchConstants.LocalGameType.BaseType.GetMethod("method_10", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
return typeof(GameWorld).GetMethod(nameof(GameWorld.OnGameStarted));
|
||||
}
|
||||
|
||||
[PatchPostfix]
|
||||
public static void PatchPostFix()
|
||||
public static void PatchPostfix()
|
||||
{
|
||||
var gameWorld = Singleton<GameWorld>.Instance;
|
||||
var crashAvailable = LocationScene.GetAll<AirdropPoint>().Any();
|
||||
string location = gameWorld.RegisteredPlayers[0].Location;
|
||||
|
||||
if (gameWorld != null && crashAvailable && WillHeliCrash())
|
||||
{
|
||||
var heliCrash = gameWorld.gameObject.AddComponent<HeliCrash>();
|
||||
heliCrash.Init(location);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool WillHeliCrash()
|
||||
{
|
||||
return Random.Range(0, 100) <= Plugin.HeliCrashChance.Value;
|
||||
var location = gameWorld.RegisteredPlayers[0].Location;
|
||||
|
||||
if (gameWorld == null || !crashAvailable || !BlessRNG.RngBool(Plugin.HeliCrashChance.Value)) return;
|
||||
|
||||
var heliCrash = gameWorld.gameObject.AddComponent<HeliCrash>();
|
||||
heliCrash.Init(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,21 +2,25 @@
|
||||
using BepInEx.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using BepInEx.Logging;
|
||||
|
||||
namespace SamSWAT.HeliCrash
|
||||
{
|
||||
[BepInPlugin("com.SamSWAT.HeliCrash", "SamSWAT.HeliCrash", "1.1.0")]
|
||||
[BepInPlugin("com.SamSWAT.HeliCrash", "SamSWAT.HeliCrash", "2.1.0")]
|
||||
public class Plugin : BaseUnityPlugin
|
||||
{
|
||||
public static HeliCrashLocations HeliCrashLocations;
|
||||
internal static HeliCrashLocations HeliCrashLocations;
|
||||
internal static string Directory;
|
||||
internal static ConfigEntry<int> HeliCrashChance;
|
||||
internal static ManualLogSource LogSource;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Directory = Path.Combine(BepInEx.Paths.PluginPath, "SamSWAT.HeliCrash/").Replace("\\", "/");
|
||||
LogSource = Logger;
|
||||
Directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
new HeliCrashPatch().Enable();
|
||||
var json = new StreamReader(Directory + "HeliCrashLocations.json").ReadToEnd();
|
||||
var json = File.ReadAllText($"{Directory}/HeliCrashLocations.json");
|
||||
HeliCrashLocations = JsonConvert.DeserializeObject<HeliCrashLocations>(json);
|
||||
|
||||
HeliCrashChance = Config.Bind(
|
||||
|
BIN
project/SamSWAT.HeliCrash/References/Aki.Common.dll
Normal file
BIN
project/SamSWAT.HeliCrash/References/Aki.Common.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
project/SamSWAT.HeliCrash/References/aki-custom.dll
Normal file
BIN
project/SamSWAT.HeliCrash/References/aki-custom.dll
Normal file
Binary file not shown.
@ -31,10 +31,14 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="aki-custom">
|
||||
<HintPath>References\aki-custom.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Aki.Reflection">
|
||||
<HintPath>References\Aki.Reflection.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp">
|
||||
<Reference Include="Assembly-CSharp, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>References\Assembly-CSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="BepInEx">
|
||||
@ -59,10 +63,12 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="HeliCrash.cs" />
|
||||
<Compile Include="HeliCrashLocations.cs" />
|
||||
<Compile Include="HeliCrashPatch.cs" />
|
||||
<Compile Include="Plugin.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Utils\BlessRNG.cs" />
|
||||
<Compile Include="Utils\HeliCrashLocations.cs" />
|
||||
<Compile Include="Utils\Utils.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
38
project/SamSWAT.HeliCrash/Utils/BlessRNG.cs
Normal file
38
project/SamSWAT.HeliCrash/Utils/BlessRNG.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace SamSWAT.HeliCrash
|
||||
{
|
||||
internal static class BlessRNG
|
||||
{
|
||||
private static readonly Random Rng = new Random((int) DateTime.Now.Ticks);
|
||||
|
||||
private static float Random(float a, float b)
|
||||
{
|
||||
var num = (float) Rng.NextDouble();
|
||||
return a + (b - a) * num;
|
||||
}
|
||||
|
||||
public static T SelectRandom<T>(this IReadOnlyList<T> list)
|
||||
{
|
||||
if (list.Count == 0)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var index = Rng.Next(0, list.Count);
|
||||
return list[index];
|
||||
}
|
||||
|
||||
public static bool RngBool(float chanceInPercent = 50f)
|
||||
{
|
||||
return Random(0f, 100f) < chanceInPercent;
|
||||
}
|
||||
|
||||
internal static List<T> Shuffle<T>(this List<T> l)
|
||||
{
|
||||
return l.OrderBy(x => Random(0.0f, 5f)).ToList();
|
||||
}
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ namespace SamSWAT.HeliCrash
|
||||
public List<Location> Lighthouse { get; set; }
|
||||
public List<Location> Rezerv { get; set; }
|
||||
public List<Location> Shoreline { get; set; }
|
||||
public List<Location> StreetsOfTarkov { get; set; }
|
||||
public List<Location> Develop { get; set; }
|
||||
}
|
||||
}
|
131
project/SamSWAT.HeliCrash/Utils/Utils.cs
Normal file
131
project/SamSWAT.HeliCrash/Utils/Utils.cs
Normal file
@ -0,0 +1,131 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using Comfort.Common;
|
||||
using EFT.InventoryLogic;
|
||||
|
||||
namespace SamSWAT.HeliCrash
|
||||
{
|
||||
public static class Utils
|
||||
{
|
||||
private static CreateItemDelegate _createItemDelegate;
|
||||
private delegate Item CreateItemDelegate(object instance, string id, string tplId, object diff = null);
|
||||
|
||||
static Utils()
|
||||
{
|
||||
var createItemMethod = typeof(ItemFactory).GetMethod("CreateItem");
|
||||
_createItemDelegate = MethodDelegate<CreateItemDelegate>(createItemMethod, false);
|
||||
}
|
||||
|
||||
public static Item CreateItem(string id, string tplId)
|
||||
{
|
||||
return _createItemDelegate(Singleton<ItemFactory>.Instance, id, tplId);
|
||||
}
|
||||
|
||||
//stolen from kmyuhkyuk
|
||||
private static DelegateType MethodDelegate<DelegateType>(MethodInfo method, bool virtualCall = true) where DelegateType : Delegate
|
||||
{
|
||||
if (method == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(method));
|
||||
}
|
||||
|
||||
var delegateType = typeof(DelegateType);
|
||||
|
||||
var declaringType = method.DeclaringType;
|
||||
|
||||
var delegateMethod = delegateType.GetMethod("Invoke");
|
||||
var delegateParameters = delegateMethod.GetParameters();
|
||||
var delegateParameterTypes = delegateParameters.Select(x => x.ParameterType).ToArray();
|
||||
|
||||
Type returnType;
|
||||
bool needBox;
|
||||
|
||||
if (delegateMethod.ReturnType == typeof(object) && method.ReturnType.IsValueType)
|
||||
{
|
||||
returnType = typeof(object);
|
||||
|
||||
needBox = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
returnType = method.ReturnType;
|
||||
|
||||
needBox = false;
|
||||
}
|
||||
|
||||
var dmd = new DynamicMethod("OpenInstanceDelegate_" + method.Name, returnType, delegateParameterTypes);
|
||||
|
||||
var ilGen = dmd.GetILGenerator();
|
||||
|
||||
Type[] parameterTypes;
|
||||
int num;
|
||||
|
||||
if (!method.IsStatic)
|
||||
{
|
||||
var parameters = method.GetParameters();
|
||||
var numParameters = parameters.Length;
|
||||
parameterTypes = new Type[numParameters + 1];
|
||||
parameterTypes[0] = typeof(object);
|
||||
|
||||
for (int i = 0; i < numParameters; i++)
|
||||
{
|
||||
parameterTypes[i + 1] = parameters[i].ParameterType;
|
||||
}
|
||||
|
||||
if (declaringType != null && declaringType.IsValueType)
|
||||
{
|
||||
ilGen.Emit(OpCodes.Ldarga_S, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ilGen.Emit(OpCodes.Ldarg_0);
|
||||
}
|
||||
|
||||
ilGen.Emit(OpCodes.Castclass, declaringType);
|
||||
|
||||
num = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
parameterTypes = method.GetParameters().Select(x => x.ParameterType).ToArray();
|
||||
|
||||
num = 0;
|
||||
}
|
||||
|
||||
for (int i = num; i < parameterTypes.Length; i++)
|
||||
{
|
||||
ilGen.Emit(OpCodes.Ldarg, i);
|
||||
var parameterType = parameterTypes[i];
|
||||
var isValueType = parameterType.IsValueType;
|
||||
if (!isValueType)
|
||||
{
|
||||
ilGen.Emit(OpCodes.Castclass, parameterType);
|
||||
}
|
||||
else if (delegateParameterTypes[i] == typeof(object))
|
||||
{
|
||||
ilGen.Emit(OpCodes.Unbox_Any, parameterType);
|
||||
}
|
||||
}
|
||||
|
||||
if (method.IsStatic || !virtualCall)
|
||||
{
|
||||
ilGen.Emit(OpCodes.Call, method);
|
||||
}
|
||||
else
|
||||
{
|
||||
ilGen.Emit(OpCodes.Callvirt, method);
|
||||
}
|
||||
|
||||
if (needBox)
|
||||
{
|
||||
ilGen.Emit(OpCodes.Box, method.ReturnType);
|
||||
}
|
||||
|
||||
ilGen.Emit(OpCodes.Ret);
|
||||
|
||||
return (DelegateType)dmd.CreateDelegate(delegateType);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user