Copying to Plugins folder on build Registering deterministic game engines automatically Each event handler is wrapped so if one fails it will still trigger the rest
280 lines
9.8 KiB
C#
280 lines
9.8 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using TechbloxModdingAPI.App;
|
|
using HarmonyLib;
|
|
using IllusionInjector;
|
|
// test
|
|
using RobocraftX.FrontEnd;
|
|
using Unity.Mathematics;
|
|
using UnityEngine;
|
|
using RobocraftX.Common.Input;
|
|
using TechbloxModdingAPI.Blocks;
|
|
using TechbloxModdingAPI.Commands;
|
|
using TechbloxModdingAPI.Input;
|
|
using TechbloxModdingAPI.Interface.IMGUI;
|
|
using TechbloxModdingAPI.Players;
|
|
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>
|
|
public class TechbloxModdingAPIPluginTest : IllusionPlugin.IEnhancedPlugin
|
|
{
|
|
|
|
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()
|
|
{
|
|
Main.Shutdown();
|
|
}
|
|
|
|
public override void OnApplicationStart()
|
|
{
|
|
FileLog.Reset();
|
|
Harmony.DEBUG = true;
|
|
Main.Init();
|
|
Logging.MetaDebugLog($"Version group id {(uint)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!");
|
|
|
|
// 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();
|
|
|
|
GameClient.SetDebugInfo("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("This is text!", 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))*/
|
|
#if TEST
|
|
TestRoot.RunTests();
|
|
#endif
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
public override void OnUpdate()
|
|
{
|
|
if (UnityEngine.Input.GetKeyDown(KeyCode.End))
|
|
{
|
|
Console.WriteLine("Pressed button to toggle console");
|
|
FakeInput.CustomInput(new LocalInputEntityStruct {commandLineToggleInput = true});
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch]
|
|
public class MinimumSpecsPatch
|
|
{
|
|
public static bool Prefix()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public static MethodInfo TargetMethod()
|
|
{
|
|
return ((Action) MinimumSpecsCheck.CheckRequirementsMet).Method;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|