diff --git a/Libraries/SPTarkov.Reflection/CodeWrapper/Code.cs b/Libraries/SPTarkov.Reflection/CodeWrapper/Code.cs
new file mode 100644
index 00000000..87c8d832
--- /dev/null
+++ b/Libraries/SPTarkov.Reflection/CodeWrapper/Code.cs
@@ -0,0 +1,46 @@
+using System.Reflection.Emit;
+
+namespace SPTarkov.Reflection.CodeWrapper;
+
+public class Code
+{
+ public OpCode OpCode { get; }
+ public Type? CallerType { get; }
+ public object? OperandTarget { get; }
+ public Type[]? Parameters { get; }
+ public bool HasOperand { get; }
+
+ public Code(OpCode opCode)
+ {
+ OpCode = opCode;
+ HasOperand = false;
+ }
+
+ public Code(OpCode opCode, object operandTarget)
+ {
+ OpCode = opCode;
+ OperandTarget = operandTarget;
+ HasOperand = true;
+ }
+
+ public Code(OpCode opCode, Type callerType)
+ {
+ OpCode = opCode;
+ CallerType = callerType;
+ HasOperand = true;
+ }
+
+ public Code(OpCode opCode, Type callerType, object operandTarget, Type[] parameters = null)
+ {
+ OpCode = opCode;
+ CallerType = callerType;
+ OperandTarget = operandTarget;
+ Parameters = parameters;
+ HasOperand = true;
+ }
+
+ public virtual Label? GetLabel()
+ {
+ return null;
+ }
+}
diff --git a/Libraries/SPTarkov.Reflection/CodeWrapper/CodeGenerator.cs b/Libraries/SPTarkov.Reflection/CodeWrapper/CodeGenerator.cs
new file mode 100644
index 00000000..2c68965d
--- /dev/null
+++ b/Libraries/SPTarkov.Reflection/CodeWrapper/CodeGenerator.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection.Emit;
+using HarmonyLib;
+
+namespace SPTarkov.Reflection.CodeWrapper;
+
+///
+/// Helper class to generate IL code for transpilers
+///
+public class CodeGenerator
+{
+ public static List GenerateInstructions(List codes)
+ {
+ var list = new List();
+
+ foreach (Code code in codes)
+ {
+ list.Add(ParseCode(code));
+ }
+
+ return list;
+ }
+
+ private static CodeInstruction ParseCode(Code code)
+ {
+ if (!code.HasOperand)
+ {
+ return new CodeInstruction(code.OpCode) { labels = GetLabelList(code) };
+ }
+
+ if (code.OpCode == OpCodes.Ldfld || code.OpCode == OpCodes.Ldflda || code.OpCode == OpCodes.Stfld)
+ {
+ return new CodeInstruction(code.OpCode, AccessTools.Field(code.CallerType, code.OperandTarget as string)) { labels = GetLabelList(code) };
+ }
+
+ if (code.OpCode == OpCodes.Call || code.OpCode == OpCodes.Callvirt)
+ {
+ return new CodeInstruction(code.OpCode, AccessTools.Method(code.CallerType, code.OperandTarget as string, code.Parameters)) { labels = GetLabelList(code) };
+ }
+
+ if (code.OpCode == OpCodes.Box)
+ {
+ return new CodeInstruction(code.OpCode, code.CallerType) { labels = GetLabelList(code) };
+ }
+
+ if (code.OpCode == OpCodes.Br || code.OpCode == OpCodes.Brfalse || code.OpCode == OpCodes.Brtrue || code.OpCode == OpCodes.Brtrue_S
+ || code.OpCode == OpCodes.Brfalse_S || code.OpCode == OpCodes.Br_S)
+ {
+ return new CodeInstruction(code.OpCode, code.OperandTarget) { labels = GetLabelList(code) };
+ }
+
+ if (code.OpCode == OpCodes.Ldftn)
+ {
+ return new CodeInstruction(code.OpCode, AccessTools.Method(code.CallerType, code.OperandTarget as string, code.Parameters)) { labels = GetLabelList(code) };
+ }
+
+ if (code.OpCode == OpCodes.Newobj)
+ {
+ return new CodeInstruction(code.OpCode, code.CallerType.GetConstructors().FirstOrDefault(x => x.GetParameters().Length == code.Parameters.Length)) { labels = GetLabelList(code) };
+ }
+
+ throw new ArgumentException($"Code with OpCode {code.OpCode.ToString()} is not supported.");
+ }
+
+ private static List