|
|
@@ -1,406 +1,84 @@ |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Diagnostics; |
|
|
|
using System.Linq; |
|
|
|
using System.Reflection; |
|
|
|
using System.Text; |
|
|
|
using System.Text.RegularExpressions; |
|
|
|
using DataLoader; |
|
|
|
using TechbloxModdingAPI.App; |
|
|
|
using BepInEx; |
|
|
|
using BepInEx.Bootstrap; |
|
|
|
using HarmonyLib; |
|
|
|
using IllusionInjector; |
|
|
|
// test |
|
|
|
using RobocraftX.FrontEnd; |
|
|
|
using ServiceLayer; |
|
|
|
using Unity.Mathematics; |
|
|
|
using UnityEngine; |
|
|
|
using Svelto.Tasks; |
|
|
|
using Svelto.Tasks.Lean; |
|
|
|
using TechbloxModdingAPI.Blocks; |
|
|
|
using TechbloxModdingAPI.App; |
|
|
|
using TechbloxModdingAPI.Commands; |
|
|
|
using TechbloxModdingAPI.Players; |
|
|
|
using TechbloxModdingAPI.Tasks; |
|
|
|
using TechbloxModdingAPI.Utility; |
|
|
|
|
|
|
|
namespace TechbloxModdingAPI.Tests |
|
|
|
{ |
|
|
|
#if DEBUG |
|
|
|
// unused by design |
|
|
|
/// <summary> |
|
|
|
/// Modding API implemented as a standalone IPA Plugin. |
|
|
|
/// Ideally, TechbloxModdingAPI should be loaded by another mod; not itself |
|
|
|
/// </summary> |
|
|
|
class TechbloxModdingAPIPluginTest : IllusionPlugin.IEnhancedPlugin |
|
|
|
#if DEBUG // The API should be loaded by other plugins, but it can be used by itself for testing |
|
|
|
[BepInPlugin("org.exmods.TechbloxModdingAPIPluginTest", PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)] |
|
|
|
[BepInProcess("Techblox.exe")] |
|
|
|
public class TechbloxModdingAPIPluginTest : BaseUnityPlugin |
|
|
|
{ |
|
|
|
|
|
|
|
private static Harmony harmony { get; set; } |
|
|
|
|
|
|
|
public override string Name { get; } = Assembly.GetExecutingAssembly().GetName().Name; |
|
|
|
|
|
|
|
public override string Version { get; } = Assembly.GetExecutingAssembly().GetName().Version.ToString(); |
|
|
|
|
|
|
|
public string HarmonyID { get; } = "org.git.exmods.modtainers.techbloxmoddingapi"; |
|
|
|
|
|
|
|
public override void OnApplicationQuit() |
|
|
|
private void Awake() |
|
|
|
{ |
|
|
|
Main.Shutdown(); |
|
|
|
} |
|
|
|
|
|
|
|
public override void OnApplicationStart() |
|
|
|
{ |
|
|
|
FileLog.Reset(); |
|
|
|
Harmony.DEBUG = true; |
|
|
|
Main.Init(); |
|
|
|
Logging.MetaDebugLog($"Version group id {ApiExclusiveGroups.versionGroup}"); |
|
|
|
// disable background music |
|
|
|
Logging.MetaDebugLog("Audio Mixers: " + string.Join(",", AudioTools.GetMixers())); |
|
|
|
//AudioTools.SetVolume(0.0f, "Music"); // The game now sets this from settings again after this is called :( |
|
|
|
|
|
|
|
//Utility.VersionTracking.Enable();//(very) unstable |
|
|
|
|
|
|
|
// debug/test handlers |
|
|
|
Client.EnterMenu += (sender, args) => throw new Exception("Test handler always throws an exception!"); |
|
|
|
Client.EnterMenu += (sender, args) => Console.WriteLine("EnterMenu handler after erroring handler"); |
|
|
|
Game.Enter += (s, a) => |
|
|
|
{ |
|
|
|
Player.LocalPlayer.SeatEntered += (sender, args) => |
|
|
|
Console.WriteLine($"Player {Player.LocalPlayer} entered seat {args.Seat}"); |
|
|
|
Player.LocalPlayer.SeatExited += (sender, args) => |
|
|
|
Console.WriteLine($"Player {Player.LocalPlayer} exited seat {args.Seat}"); |
|
|
|
}; |
|
|
|
|
|
|
|
// debug/test commands |
|
|
|
if (Dependency.Hell("ExtraCommands")) |
|
|
|
{ |
|
|
|
CommandBuilder.Builder() |
|
|
|
.Name("Exit") |
|
|
|
.Description("Close Techblox immediately, without any prompts") |
|
|
|
.Action(() => { UnityEngine.Application.Quit(); }) |
|
|
|
.Build(); |
|
|
|
|
|
|
|
CommandBuilder.Builder() |
|
|
|
.Name("SetFOV") |
|
|
|
.Description("Set the player camera's field of view") |
|
|
|
.Action((float d) => { UnityEngine.Camera.main.fieldOfView = d; }) |
|
|
|
.Build(); |
|
|
|
|
|
|
|
CommandBuilder.Builder() |
|
|
|
.Name("MoveLastBlock") |
|
|
|
.Description("Move the most-recently-placed block, and any connected blocks by the given offset") |
|
|
|
.Action((float x, float y, float z) => |
|
|
|
{ |
|
|
|
if (GameState.IsBuildMode()) |
|
|
|
foreach (var block in Block.GetLastPlacedBlock().GetConnectedCubes()) |
|
|
|
block.Position += new Unity.Mathematics.float3(x, y, z); |
|
|
|
else |
|
|
|
Logging.CommandLogError("Blocks can only be moved in Build mode!"); |
|
|
|
}).Build(); |
|
|
|
|
|
|
|
CommandBuilder.Builder() |
|
|
|
.Name("PlaceAluminium") |
|
|
|
.Description("Place a block of aluminium at the given coordinates") |
|
|
|
.Action((float x, float y, float z) => |
|
|
|
{ |
|
|
|
var block = Block.PlaceNew(BlockIDs.Cube, new float3(x, y, z)); |
|
|
|
Logging.CommandLog("Block placed with type: " + block.Type); |
|
|
|
}) |
|
|
|
.Build(); |
|
|
|
|
|
|
|
CommandBuilder.Builder() |
|
|
|
.Name("PlaceAluminiumLots") |
|
|
|
.Description("Place a lot of blocks of aluminium at the given coordinates") |
|
|
|
.Action((float x, float y, float z) => |
|
|
|
{ |
|
|
|
Logging.CommandLog("Starting..."); |
|
|
|
var sw = Stopwatch.StartNew(); |
|
|
|
for (int i = 0; i < 100; i++) |
|
|
|
for (int j = 0; j < 100; j++) |
|
|
|
Block.PlaceNew(BlockIDs.Cube, new float3(x + i, y, z + j)); |
|
|
|
sw.Stop(); |
|
|
|
Logging.CommandLog("Finished in " + sw.ElapsedMilliseconds + "ms"); |
|
|
|
}) |
|
|
|
.Build(); |
|
|
|
|
|
|
|
Block b = null; |
|
|
|
CommandBuilder.Builder("moveBlockInSim", "Run in build mode first while looking at a block, then in sim to move it up") |
|
|
|
.Action(() => |
|
|
|
{ |
|
|
|
if (b == null) |
|
|
|
{ |
|
|
|
b = new Player(PlayerType.Local).GetBlockLookedAt(); |
|
|
|
Logging.CommandLog("Block saved: " + b); |
|
|
|
} |
|
|
|
else |
|
|
|
Logging.CommandLog("Block moved to: " + (b.GetSimBody().Position += new float3(0, 2, 0))); |
|
|
|
}).Build(); |
|
|
|
|
|
|
|
CommandBuilder.Builder("Error", "Throw an error to make sure SimpleCustomCommandEngine's wrapper catches it.") |
|
|
|
.Action(() => { throw new Exception("Error Command always throws an error"); }) |
|
|
|
.Build(); |
|
|
|
|
|
|
|
CommandBuilder.Builder("ColorBlock", |
|
|
|
"Change color of the block looked at if there's any.") |
|
|
|
.Action<string>(str => |
|
|
|
{ |
|
|
|
if (!Enum.TryParse(str, out BlockColors color)) |
|
|
|
{ |
|
|
|
Logging.CommandLog("Color " + str + " not found! Interpreting as 4 color values."); |
|
|
|
var s = str.Split(' '); |
|
|
|
new Player(PlayerType.Local).GetBlockLookedAt().CustomColor = new float4(float.Parse(s[0]), |
|
|
|
float.Parse(s[1]), float.Parse(s[2]), float.Parse(s[3])); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
new Player(PlayerType.Local).GetBlockLookedAt().Color = color; |
|
|
|
Logging.CommandLog("Colored block to " + color); |
|
|
|
|
|
|
|
}).Build(); |
|
|
|
|
|
|
|
CommandBuilder.Builder("MoveBlockByID", "Gets a block based on its object identifier and teleports it up.") |
|
|
|
.Action<char>(ch => |
|
|
|
{ |
|
|
|
foreach (var body in SimBody.GetFromObjectID(ch)) |
|
|
|
{ |
|
|
|
Logging.CommandLog("SimBody: " + body); |
|
|
|
body.Position += new float3(0, 10, 0); |
|
|
|
foreach (var bodyConnectedBody in body.GetConnectedBodies()) |
|
|
|
{ |
|
|
|
Logging.CommandLog("Moving " + bodyConnectedBody); |
|
|
|
bodyConnectedBody.Position += new float3(0, 10, 0); |
|
|
|
} |
|
|
|
} |
|
|
|
}).Build(); |
|
|
|
|
|
|
|
CommandBuilder.Builder("TestChunkHealth", "Sets the chunk looked at to the given health.") |
|
|
|
.Action((float val, float max) => |
|
|
|
{ |
|
|
|
var body = new Player(PlayerType.Local).GetSimBodyLookedAt(); |
|
|
|
if (body == null) return; |
|
|
|
body.CurrentHealth = val; |
|
|
|
body.InitialHealth = max; |
|
|
|
Logging.CommandLog("Health set to: " + val); |
|
|
|
}).Build(); |
|
|
|
|
|
|
|
CommandBuilder.Builder("placeBlockGroup", "Places some blocks in a group") |
|
|
|
.Action((float x, float y, float z) => |
|
|
|
{ |
|
|
|
var pos = new float3(x, y, z); |
|
|
|
var group = BlockGroup.Create(new Block(BlockIDs.Cube, pos) {Color = BlockColors.Aqua}); |
|
|
|
new Block(BlockIDs.Cube, pos += new float3(1, 0, 0)) |
|
|
|
{Color = BlockColors.Blue, BlockGroup = group}; |
|
|
|
new Block(BlockIDs.Cube, pos += new float3(1, 0, 0)) |
|
|
|
{Color = BlockColors.Green, BlockGroup = group}; |
|
|
|
new Block(BlockIDs.Cube, pos + new float3(1, 0, 0)) |
|
|
|
{Color = BlockColors.Lime, BlockGroup = group}; |
|
|
|
}).Build(); |
|
|
|
|
|
|
|
CommandBuilder.Builder("placeCustomBlock", "Places a custom block, needs a custom catalog and assets.") |
|
|
|
.Action((float x, float y, float z) => |
|
|
|
{ |
|
|
|
Logging.CommandLog("Block placed: " + |
|
|
|
Block.PlaceNew((BlockIDs) 500, new float3(0, 0, 0))); |
|
|
|
}).Build(); |
|
|
|
|
|
|
|
CommandBuilder.Builder("toggleTimeMode", "Enters or exits simulation.") |
|
|
|
.Action((float x, float y, float z) => |
|
|
|
{ |
|
|
|
Game.CurrentGame().ToggleTimeMode(); |
|
|
|
}).Build(); |
|
|
|
|
|
|
|
CommandBuilder.Builder("testColorBlock", "Tests coloring a block to default color") |
|
|
|
.Action(() => Player.LocalPlayer.GetBlockLookedAt().Color = BlockColors.Default).Build(); |
|
|
|
CommandBuilder.Builder("testMaterialBlock", "Tests materialing a block to default material") |
|
|
|
.Action(() => Player.LocalPlayer.GetBlockLookedAt().Material = BlockMaterial.Default).Build(); |
|
|
|
CommandBuilder.Builder("testGameName", "Tests changing the game name") |
|
|
|
.Action(() => Game.CurrentGame().Name = "Test").Build(); |
|
|
|
CommandBuilder.Builder("makeBlockStatic", "Makes a block you look at static") |
|
|
|
.Action(() => Player.LocalPlayer.GetBlockLookedAt().Static = true).Build(); |
|
|
|
|
|
|
|
Game.AddPersistentDebugInfo("InstalledMods", InstalledMods); |
|
|
|
/*Block.Placed += (sender, args) => |
|
|
|
Logging.MetaDebugLog("Placed block " + args.Block); |
|
|
|
Block.Removed += (sender, args) => |
|
|
|
Logging.MetaDebugLog("Removed block " + args.Block);*/ |
|
|
|
} |
|
|
|
|
|
|
|
// dependency test |
|
|
|
if (Dependency.Hell("TechbloxScripting", new Version("0.0.1.0"))) |
|
|
|
{ |
|
|
|
Logging.LogWarning("You're in TechbloxScripting dependency hell"); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
Logging.Log("Compatible TechbloxScripting detected"); |
|
|
|
} |
|
|
|
// Interface test |
|
|
|
/*Group uiGroup = new Group(new Rect(20, 20, 200, 500), "TechbloxModdingAPI_UITestGroup", true); |
|
|
|
var button = new Button("TEST"); |
|
|
|
button.OnClick += (b, __) => { Logging.MetaDebugLog($"Click on {((Interface.IMGUI.Button)b).Name}");}; |
|
|
|
var button2 = new Button("TEST2"); |
|
|
|
button2.OnClick += (b, __) => { Logging.MetaDebugLog($"Click on {((Interface.IMGUI.Button)b).Name}");}; |
|
|
|
Text uiText = new Text("<Input!>", multiline: true); |
|
|
|
uiText.OnEdit += (t, txt) => { Logging.MetaDebugLog($"Text in {((Text)t).Name} is now '{txt}'"); }; |
|
|
|
Label uiLabel = new Label("Label!"); |
|
|
|
Image uiImg = new Image(name:"Behold this texture!"); |
|
|
|
uiImg.Enabled = false; |
|
|
|
uiGroup.AddElement(button); |
|
|
|
uiGroup.AddElement(button2); |
|
|
|
uiGroup.AddElement(uiText); |
|
|
|
uiGroup.AddElement(uiLabel); |
|
|
|
uiGroup.AddElement(uiImg);*/ |
|
|
|
|
|
|
|
/*Addressables.LoadAssetAsync<Texture2D>("Assets/Art/Textures/UI/FrontEndMap/RCX_Blue_Background_5k.jpg") |
|
|
|
.Completed += |
|
|
|
handle => |
|
|
|
{ |
|
|
|
uiImg.Texture = handle.Result; |
|
|
|
uiImg.Enabled = true; |
|
|
|
Logging.MetaDebugLog($"Got blue bg asset {handle.Result}"); |
|
|
|
};*/ |
|
|
|
|
|
|
|
/*((FasterList<GuiInputMap.GuiInputMapElement>)AccessTools.Property(typeof(GuiInputMap), "GuiInputsButtonDown").GetValue(null)) |
|
|
|
.Add(new GuiInputMap.GuiInputMapElement(RewiredConsts.Action.ToggleCommandLine, GuiIn))*/ |
|
|
|
|
|
|
|
/*Game.Enter += (sender, e) => |
|
|
|
Main.Init(); |
|
|
|
Client.EnterMenu += (sender, args) => throw new Exception("Test handler always throws an exception!"); |
|
|
|
Client.EnterMenu += (sender, args) => Console.WriteLine("EnterMenu handler after erroring handler"); |
|
|
|
Game.Enter += (s, a) => |
|
|
|
{ |
|
|
|
ushort lastKey = ushort.MaxValue; |
|
|
|
foreach (var kv in FullGameFields._dataDb.GetValues<CubeListData>() |
|
|
|
.OrderBy(kv=>ushort.Parse(kv.Key))) |
|
|
|
{ |
|
|
|
var data = (CubeListData) kv.Value; |
|
|
|
ushort currentKey = ushort.Parse(kv.Key); |
|
|
|
var toReplace = new Dictionary<string, string> |
|
|
|
{ |
|
|
|
{"Scalable", ""}, {"Qtr", "Quarter"}, {"RNeg", "Rounded Negative"}, |
|
|
|
{"Neg", "Negative"}, {"Tetra", "Tetrahedron"}, |
|
|
|
{"RWedge", "Rounded Wedge"}, {"RTetra", "Rounded Tetrahedron"} |
|
|
|
}; |
|
|
|
string name = LocalizationService.Localize(data.CubeNameKey).Split(' ').Select(str => |
|
|
|
str.Length > 0 ? char.ToUpper(str[0]) + str.Substring(1) : str).Aggregate((a, b) => a + b) |
|
|
|
.Replace("-", ""); |
|
|
|
foreach (var rkv in toReplace) |
|
|
|
{ |
|
|
|
name = Regex.Replace(name, rkv.Key + "([A-Z]|$)", rkv.Value + "$1"); |
|
|
|
} |
|
|
|
Console.WriteLine($"{name}{(currentKey != lastKey + 1 ? $" = {currentKey}" : "")},"); |
|
|
|
lastKey = currentKey; |
|
|
|
} |
|
|
|
Player.LocalPlayer.SeatEntered += (sender, args) => |
|
|
|
Console.WriteLine($"Player {Player.LocalPlayer} entered seat {args.Seat}"); |
|
|
|
Player.LocalPlayer.SeatExited += (sender, args) => |
|
|
|
Console.WriteLine($"Player {Player.LocalPlayer} exited seat {args.Seat}"); |
|
|
|
}; |
|
|
|
Game.Enter += (sender, e) => |
|
|
|
{ |
|
|
|
ushort lastKey = ushort.MaxValue; |
|
|
|
Console.WriteLine("Materials:\n" + FullGameFields._dataDb.GetValues<MaterialPropertiesData>() |
|
|
|
.OrderBy(kv => ushort.Parse(kv.Key)) |
|
|
|
.Select(kv => |
|
|
|
{ |
|
|
|
ushort currentKey = ushort.Parse(kv.Key); |
|
|
|
string result = $"{((MaterialPropertiesData)kv.Value).Name}{(currentKey != lastKey + 1 ? $" = {kv.Key}" : "")},"; |
|
|
|
lastKey = currentKey; |
|
|
|
return result; |
|
|
|
}) |
|
|
|
.Aggregate((a, b) => a + "\n" + b)); |
|
|
|
};*/ |
|
|
|
|
|
|
|
CommandBuilder.Builder("takeScreenshot", "Enables the screenshot taker") |
|
|
|
.Action(() => |
|
|
|
{ |
|
|
|
Game.CurrentGame().EnableScreenshotTaker(); |
|
|
|
}).Build(); |
|
|
|
|
|
|
|
CommandBuilder.Builder("testPositionDefault", "Tests the Block.Position property's default value.") |
|
|
|
.Action(() => |
|
|
|
{ |
|
|
|
IEnumerator<TaskContract> Loop() |
|
|
|
{ |
|
|
|
for (int i = 0; i < 2; i++) |
|
|
|
{ |
|
|
|
Console.WriteLine("A"); |
|
|
|
var block = Block.PlaceNew(BlockIDs.Cube, 1); |
|
|
|
Console.WriteLine("B"); |
|
|
|
while (!block.Exists) |
|
|
|
yield return Yield.It; |
|
|
|
Console.WriteLine("C"); |
|
|
|
block.Remove(); |
|
|
|
Console.WriteLine("D"); |
|
|
|
while (block.Exists) |
|
|
|
yield return Yield.It; |
|
|
|
Console.WriteLine("E - Pos: " + block.Position); |
|
|
|
block.Position = 4; |
|
|
|
Console.WriteLine("F - Pos: " + block.Position); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Loop().RunOn(Scheduler.leanRunner); |
|
|
|
}).Build(); |
|
|
|
|
|
|
|
CommandBuilder.Builder("importAssetBundle") |
|
|
|
.Action(() => |
|
|
|
{ |
|
|
|
Logging.CommandLog("Importing asset bundle..."); |
|
|
|
var ab = AssetBundle.LoadFromFile( |
|
|
|
@"filepath"); |
|
|
|
Logging.CommandLog("Imported asset bundle: " + ab); |
|
|
|
var assets = ab.LoadAllAssets(); |
|
|
|
Logging.CommandLog("Loaded " + assets.Length + " assets"); |
|
|
|
foreach (var asset in assets) |
|
|
|
{ |
|
|
|
Logging.CommandLog(asset); |
|
|
|
} |
|
|
|
}).Build(); |
|
|
|
|
|
|
|
bool shouldTestGhostBlock = false; |
|
|
|
CommandBuilder.Builder("testGhostBlock") |
|
|
|
.Action(() => |
|
|
|
{ |
|
|
|
if (shouldTestGhostBlock) |
|
|
|
{ |
|
|
|
shouldTestGhostBlock = false; |
|
|
|
Logging.CommandLog("Test disabled"); |
|
|
|
} |
|
|
|
|
|
|
|
shouldTestGhostBlock = true; |
|
|
|
Scheduler.Schedule(new Repeatable(() => |
|
|
|
{ |
|
|
|
var ghostBlock = Player.LocalPlayer.GetGhostBlock(); |
|
|
|
if (ghostBlock == null) return; |
|
|
|
ghostBlock.Position = Player.LocalPlayer.Position + 2; |
|
|
|
ghostBlock.Color = new BlockColor(BlockColors.Lime); |
|
|
|
}, () => shouldTestGhostBlock)); |
|
|
|
Logging.CommandLog("Test enabled"); |
|
|
|
}).Build(); |
|
|
|
|
|
|
|
Game.Enter += (sender, args) => |
|
|
|
Console.WriteLine( |
|
|
|
$"Current game selection data: {FullGameFields._gameSelectionData.gameMode} - {FullGameFields._gameSelectionData.saveType}"); |
|
|
|
CommandBuilder.Builder() |
|
|
|
.Name("Exit") |
|
|
|
.Description("Close Techblox immediately, without any prompts") |
|
|
|
.Action(() => { UnityEngine.Application.Quit(); }) |
|
|
|
.Build(); |
|
|
|
|
|
|
|
CommandBuilder.Builder() |
|
|
|
.Name("SetFOV") |
|
|
|
.Description("Set the player camera's field of view") |
|
|
|
.Action((float d) => { UnityEngine.Camera.main.fieldOfView = d; }) |
|
|
|
.Build(); |
|
|
|
|
|
|
|
Game.AddPersistentDebugInfo("InstalledMods", InstalledMods); |
|
|
|
|
|
|
|
// Plugin startup logic |
|
|
|
Logger.LogInfo($"Plugin {PluginInfo.PLUGIN_GUID} is loaded!"); |
|
|
|
|
|
|
|
#if TEST |
|
|
|
TestRoot.RunTests(); |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private string modsString; |
|
|
|
private void OnDestroy() |
|
|
|
{ |
|
|
|
Main.Shutdown(); |
|
|
|
} |
|
|
|
|
|
|
|
private string modsString; |
|
|
|
private string InstalledMods() |
|
|
|
{ |
|
|
|
if (modsString != null) return modsString; |
|
|
|
StringBuilder sb = new StringBuilder("Installed mods:"); |
|
|
|
foreach (var plugin in PluginManager.Plugins) |
|
|
|
sb.Append("\n" + plugin.Name + " - " + plugin.Version); |
|
|
|
return modsString = sb.ToString(); |
|
|
|
if (modsString != null) return modsString; |
|
|
|
StringBuilder sb = new StringBuilder("Installed mods:"); |
|
|
|
foreach (var (_, plugin) in Chainloader.PluginInfos) |
|
|
|
sb.Append("\n" + plugin.Metadata.Name + " - " + plugin.Metadata.Version); |
|
|
|
return modsString = sb.ToString(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
[HarmonyPatch] |
|
|
|
public class MinimumSpecsPatch |
|
|
|
[HarmonyPatch] |
|
|
|
public class MinimumSpecsPatch |
|
|
|
{ |
|
|
|
public static bool Prefix(ref bool __result) |
|
|
|
{ |
|
|
|
public static bool Prefix(ref bool __result) |
|
|
|
{ |
|
|
|
__result = true; |
|
|
|
return false; |
|
|
|
} |
|
|
|
__result = true; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
public static MethodInfo TargetMethod() |
|
|
|
{ |
|
|
|
return ((Func<bool>) MinimumSpecsCheck.CheckRequirementsMet).Method; |
|
|
|
} |
|
|
|
public static MethodInfo TargetMethod() |
|
|
|
{ |
|
|
|
return ((Func<bool>) MinimumSpecsCheck.CheckRequirementsMet).Method; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
} |