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 RobocraftX.Common;
using Svelto.ECS;
using Techblox.EngineBlock;
namespace CodeGenerator
{
@ -97,6 +96,8 @@ namespace CodeGenerator
{
if (!typeof(IEntityComponent).IsAssignableFrom(type))
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())
{
var attr = field.GetCustomAttribute<TweakableStatAttribute>();
@ -108,10 +109,20 @@ namespace CodeGenerator
}
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()), field.Name);
new CodeThisReferenceExpression());
CodeExpression structFieldReference = new CodeFieldReferenceExpression(getStruct, field.Name);
CodeExpression reflectedGet = new CodeCastExpression(field.FieldType, new CodeMethodInvokeExpression(
new CodeMethodReferenceExpression(new CodeSnippetExpression("BlockEngine"),
"GetBlockInfo"),
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
{
Name = propName,
@ -119,18 +130,23 @@ namespace CodeGenerator
HasSet = true,
GetStatements =
{
new CodeMethodReturnStatement(structFieldReference)
new CodeMethodReturnStatement(reflection ? reflectedGet : structFieldReference)
},
SetStatements =
{
new CodeAssignStatement(structFieldReference, new CodePropertySetValueReferenceExpression())
reflection
? (CodeStatement)new CodeExpressionStatement(reflectedSet)
: new CodeAssignStatement(structFieldReference, new CodePropertySetValueReferenceExpression())
},
Type = new CodeTypeReference(field.FieldType),
Attributes = MemberAttributes.Public | MemberAttributes.Final,
Comments =
{
_start, new CodeCommentStatement($"Gets or sets the {baseClass}'s {propName} property." +
$" {(attr != null ? "Tweakable stat." : "May not be saved.")}", true), _end
_start,
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>
</PropertyGroup>
<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.Core" />
<Reference Include="System.Data" />
@ -1164,6 +1168,16 @@
<HintPath>..\..\ref\Techblox_Data\Managed\VisualProfiler.dll</HintPath>
</Reference>
</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" />
<!-- 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.

View file

@ -1,4 +1,5 @@
using System.Collections.Generic;
using HarmonyLib;
using RobocraftX.Blocks;
using RobocraftX.PilotSeat;
using Techblox.EngineBlock;
@ -11,11 +12,11 @@ namespace CodeGenerator
public static void Main(string[] args)
{
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
}, typeof(EngineBlockComponent), // Simulation time properties
typeof(EngineBlockTweakableComponent), typeof(EngineBlockReadonlyComponent));*/
{ "engineOn", "On" }
}, AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), // Simulation time properties
typeof(EngineBlockTweakableComponent), typeof(EngineBlockReadonlyComponent));
bcg.Generate("DampedSpring", "DAMPEDSPRING_BLOCK_GROUP", new Dictionary<string, string>
{
{"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))
{
}
/*
/// <summary>
/// Gets or sets the Engine's On property. May not be saved.
/// </summary>
@ -30,12 +30,11 @@ namespace TechbloxModdingAPI.Blocks
{
get
{
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).engineOn;
return ((bool)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "engineOn")));
}
set
{
Techblox.BlockColours.BlockColoursCompositionRoot
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).engineOn = value;
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "engineOn", value);
}
}
@ -46,11 +45,11 @@ namespace TechbloxModdingAPI.Blocks
{
get
{
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentGear;
return ((int)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentGear")));
}
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
{
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).gearChangeCountdown;
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "gearChangeCountdown")));
}
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
{
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentRpmAV;
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentRpmAV")));
}
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
{
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentRpmLV;
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentRpmLV")));
}
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
{
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).targetRpmAV;
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "targetRpmAV")));
}
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
{
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).targetRpmLV;
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "targetRpmLV")));
}
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
{
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentTorque;
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentTorque")));
}
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
{
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).totalWheelVelocityAV;
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelVelocityAV")));
}
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
{
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).totalWheelVelocityLV;
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelVelocityLV")));
}
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
{
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).totalWheelCount;
return ((int)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelCount")));
}
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
{
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).lastGearUpInput;
return ((bool)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "lastGearUpInput")));
}
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
{
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).lastGearDownInput;
return ((bool)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "lastGearDownInput")));
}
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
{
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).manualToAutoGearCoolOffCounter;
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "manualToAutoGearCoolOffCounter")));
}
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
{
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).load;
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "load")));
}
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;
}
}*/
}
}
}

View file

@ -97,6 +97,20 @@ namespace TechbloxModdingAPI.Blocks.Engines
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)
{
if (!BlockExists(id)) return;