Add support for generating block classes that use reflection to access internal components

Added Engine properties again
This commit is contained in:
Norbi Peti 2022-02-06 03:11:51 +01:00
parent 4684b33c69
commit 5fea7dc3b3
7 changed files with 103 additions and 45 deletions

10
CodeGenerator/App.config Normal file
View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?><configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="mscorlib" publicKeyToken="b77a5c561934e089" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View file

@ -8,7 +8,6 @@ using System.Reflection;
using Gamecraft.Tweaks; using Gamecraft.Tweaks;
using RobocraftX.Common; using RobocraftX.Common;
using Svelto.ECS; using Svelto.ECS;
using Techblox.EngineBlock;
namespace CodeGenerator namespace CodeGenerator
{ {
@ -97,6 +96,8 @@ namespace CodeGenerator
{ {
if (!typeof(IEntityComponent).IsAssignableFrom(type)) if (!typeof(IEntityComponent).IsAssignableFrom(type))
throw new ArgumentException("Type must be an entity component"); throw new ArgumentException("Type must be an entity component");
bool reflection = type.IsNotPublic;
var reflectedType = new CodeSnippetExpression($"HarmonyLib.AccessTools.TypeByName(\"{type.FullName}\")");
foreach (var field in type.GetFields()) foreach (var field in type.GetFields())
{ {
var attr = field.GetCustomAttribute<TweakableStatAttribute>(); var attr = field.GetCustomAttribute<TweakableStatAttribute>();
@ -108,10 +109,20 @@ namespace CodeGenerator
} }
propName = char.ToUpper(propName[0]) + propName.Substring(1); propName = char.ToUpper(propName[0]) + propName.Substring(1);
var structFieldReference = new CodeFieldReferenceExpression(new CodeMethodInvokeExpression( var getStruct = new CodeMethodInvokeExpression(
new CodeMethodReferenceExpression(new CodeSnippetExpression("BlockEngine"),
"GetBlockInfo", new CodeTypeReference(type)),
new CodeThisReferenceExpression());
CodeExpression structFieldReference = new CodeFieldReferenceExpression(getStruct, field.Name);
CodeExpression reflectedGet = new CodeCastExpression(field.FieldType, new CodeMethodInvokeExpression(
new CodeMethodReferenceExpression(new CodeSnippetExpression("BlockEngine"), new CodeMethodReferenceExpression(new CodeSnippetExpression("BlockEngine"),
"GetBlockInfo", new CodeTypeReference(type)), "GetBlockInfo"),
new CodeThisReferenceExpression()), field.Name); new CodeThisReferenceExpression(), reflectedType, new CodePrimitiveExpression(field.Name)));
CodeExpression reflectedSet = new CodeMethodInvokeExpression(
new CodeMethodReferenceExpression(new CodeSnippetExpression("BlockEngine"),
"SetBlockInfo"),
new CodeThisReferenceExpression(), reflectedType, new CodePrimitiveExpression(field.Name),
new CodePropertySetValueReferenceExpression());
cl.Members.Add(new CodeMemberProperty cl.Members.Add(new CodeMemberProperty
{ {
Name = propName, Name = propName,
@ -119,18 +130,23 @@ namespace CodeGenerator
HasSet = true, HasSet = true,
GetStatements = GetStatements =
{ {
new CodeMethodReturnStatement(structFieldReference) new CodeMethodReturnStatement(reflection ? reflectedGet : structFieldReference)
}, },
SetStatements = SetStatements =
{ {
new CodeAssignStatement(structFieldReference, new CodePropertySetValueReferenceExpression()) reflection
? (CodeStatement)new CodeExpressionStatement(reflectedSet)
: new CodeAssignStatement(structFieldReference, new CodePropertySetValueReferenceExpression())
}, },
Type = new CodeTypeReference(field.FieldType), Type = new CodeTypeReference(field.FieldType),
Attributes = MemberAttributes.Public | MemberAttributes.Final, Attributes = MemberAttributes.Public | MemberAttributes.Final,
Comments = Comments =
{ {
_start, new CodeCommentStatement($"Gets or sets the {baseClass}'s {propName} property." + _start,
$" {(attr != null ? "Tweakable stat." : "May not be saved.")}", true), _end new CodeCommentStatement($"Gets or sets the {baseClass}'s {propName} property." +
$" {(attr != null ? "Tweakable stat." : "May not be saved.")}",
true),
_end
} }
}); });
} }

View file

@ -32,6 +32,10 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="0Harmony, Version=2.2.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\packages\Lib.Harmony.2.2.0\lib\net472\0Harmony.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
@ -1164,6 +1168,16 @@
<HintPath>..\..\ref\Techblox_Data\Managed\VisualProfiler.dll</HintPath> <HintPath>..\..\ref\Techblox_Data\Managed\VisualProfiler.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TechbloxModdingAPI\TechbloxModdingAPI.csproj">
<Project>{7fd5a7d8-4f3e-426a-b07d-7dc70442a4df}</Project>
<Name>TechbloxModdingAPI</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View file

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using HarmonyLib;
using RobocraftX.Blocks; using RobocraftX.Blocks;
using RobocraftX.PilotSeat; using RobocraftX.PilotSeat;
using Techblox.EngineBlock; using Techblox.EngineBlock;
@ -11,11 +12,11 @@ namespace CodeGenerator
public static void Main(string[] args) public static void Main(string[] args)
{ {
var bcg = new BlockClassGenerator(); var bcg = new BlockClassGenerator();
/*bcg.Generate("Engine", null, new Dictionary<string, string> bcg.Generate("Engine", null, new Dictionary<string, string>
{ {
{ "engineOn", "On" } - TODO: Internal struct { "engineOn", "On" }
}, typeof(EngineBlockComponent), // Simulation time properties }, AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), // Simulation time properties
typeof(EngineBlockTweakableComponent), typeof(EngineBlockReadonlyComponent));*/ typeof(EngineBlockTweakableComponent), typeof(EngineBlockReadonlyComponent));
bcg.Generate("DampedSpring", "DAMPEDSPRING_BLOCK_GROUP", new Dictionary<string, string> bcg.Generate("DampedSpring", "DAMPEDSPRING_BLOCK_GROUP", new Dictionary<string, string>
{ {
{"maxExtent", "MaxExtension"} {"maxExtent", "MaxExtension"}

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Lib.Harmony" version="2.2.0" targetFramework="net472" />
</packages>

View file

@ -22,7 +22,7 @@ namespace TechbloxModdingAPI.Blocks
base(new EGID(id, CommonExclusiveGroups.ENGINE_BLOCK_BUILD_GROUP)) base(new EGID(id, CommonExclusiveGroups.ENGINE_BLOCK_BUILD_GROUP))
{ {
} }
/*
/// <summary> /// <summary>
/// Gets or sets the Engine's On property. May not be saved. /// Gets or sets the Engine's On property. May not be saved.
/// </summary> /// </summary>
@ -30,12 +30,11 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).engineOn; return ((bool)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "engineOn")));
} }
set set
{ {
Techblox.BlockColours.BlockColoursCompositionRoot BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "engineOn", value);
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).engineOn = value;
} }
} }
@ -46,11 +45,11 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentGear; return ((int)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentGear")));
} }
set set
{ {
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentGear = value; BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentGear", value);
} }
} }
@ -61,11 +60,11 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).gearChangeCountdown; return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "gearChangeCountdown")));
} }
set set
{ {
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).gearChangeCountdown = value; BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "gearChangeCountdown", value);
} }
} }
@ -76,11 +75,11 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentRpmAV; return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentRpmAV")));
} }
set set
{ {
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentRpmAV = value; BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentRpmAV", value);
} }
} }
@ -91,11 +90,11 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentRpmLV; return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentRpmLV")));
} }
set set
{ {
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentRpmLV = value; BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentRpmLV", value);
} }
} }
@ -106,11 +105,11 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).targetRpmAV; return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "targetRpmAV")));
} }
set set
{ {
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).targetRpmAV = value; BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "targetRpmAV", value);
} }
} }
@ -121,11 +120,11 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).targetRpmLV; return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "targetRpmLV")));
} }
set set
{ {
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).targetRpmLV = value; BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "targetRpmLV", value);
} }
} }
@ -136,11 +135,11 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentTorque; return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentTorque")));
} }
set set
{ {
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentTorque = value; BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentTorque", value);
} }
} }
@ -151,11 +150,11 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).totalWheelVelocityAV; return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelVelocityAV")));
} }
set set
{ {
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).totalWheelVelocityAV = value; BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelVelocityAV", value);
} }
} }
@ -166,11 +165,11 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).totalWheelVelocityLV; return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelVelocityLV")));
} }
set set
{ {
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).totalWheelVelocityLV = value; BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelVelocityLV", value);
} }
} }
@ -181,11 +180,11 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).totalWheelCount; return ((int)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelCount")));
} }
set set
{ {
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).totalWheelCount = value; BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelCount", value);
} }
} }
@ -196,11 +195,11 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).lastGearUpInput; return ((bool)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "lastGearUpInput")));
} }
set set
{ {
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).lastGearUpInput = value; BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "lastGearUpInput", value);
} }
} }
@ -211,11 +210,11 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).lastGearDownInput; return ((bool)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "lastGearDownInput")));
} }
set set
{ {
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).lastGearDownInput = value; BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "lastGearDownInput", value);
} }
} }
@ -226,11 +225,11 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).manualToAutoGearCoolOffCounter; return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "manualToAutoGearCoolOffCounter")));
} }
set set
{ {
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).manualToAutoGearCoolOffCounter = value; BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "manualToAutoGearCoolOffCounter", value);
} }
} }
@ -241,11 +240,11 @@ namespace TechbloxModdingAPI.Blocks
{ {
get get
{ {
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).load; return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "load")));
} }
set set
{ {
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).load = value; BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "load", value);
} }
} }
@ -378,6 +377,6 @@ namespace TechbloxModdingAPI.Blocks
{ {
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockReadonlyComponent>(this).manualToAutoGearCoolOffTime = value; BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockReadonlyComponent>(this).manualToAutoGearCoolOffTime = value;
} }
}*/ }
} }
} }

View file

@ -97,6 +97,20 @@ namespace TechbloxModdingAPI.Blocks.Engines
return ref entitiesDB.QueryEntityOrDefault<T>(block); return ref entitiesDB.QueryEntityOrDefault<T>(block);
} }
internal object GetBlockInfo(Block block, Type type, string name)
{
var str = AccessTools.Method(typeof(BlockEngine), "GetBlockInfo", generics: new[] { type })
.Invoke(this, new object[] { block });
return AccessTools.Field(str.GetType(), name).GetValue(str);
}
internal void SetBlockInfo(Block block, Type type, string name, object value)
{
var str = AccessTools.Method(typeof(BlockEngine), "GetBlockInfo", generics: new[] { type })
.Invoke(this, new object[] { block });
AccessTools.Field(str.GetType(), name).SetValue(str, value);
}
public void UpdateDisplayedBlock(EGID id) public void UpdateDisplayedBlock(EGID id)
{ {
if (!BlockExists(id)) return; if (!BlockExists(id)) return;