Repository: paradoxical-autumn/ArbitraryComponentAccess
Pull request #4: rework the entire freaking plugin
Author: login: ErrorJan
Created: 2025-03-18T16:31:01Z | Merged: 2025-03-18T21:13:08Z

New additions
- FindComponentInChilldren
- FindComponentInChildren<T>
- FindComponentInParents
- FindComponentInParents<T>
- FieldToString
- New SourceGen

Fixes:
- Some ProtoFlux Classes has Category instead of NodeCategory.
- Added NodeCategory to some Classes


Diff:
diff --git a/.gitignore b/.gitignore
index 37e7c61..9b835f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 # ErrorJan's additional thingies
 additionalPlugins/
 rml_*/
+generator_debug_log.txt
 
 # autumn's additional thingies
 open_resonite.cmd
diff --git a/ArbitraryComponentAccess.sln b/ArbitraryComponentAccess.sln
index d6b613c..dea499a 100644
--- a/ArbitraryComponentAccess.sln
+++ b/ArbitraryComponentAccess.sln
@@ -5,13 +5,13 @@ VisualStudioVersion = 17.11.35327.3
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArbitraryComponentAccess", "ArbitraryComponentAccess\ArbitraryComponentAccess.csproj", "{49341FFD-B153-419D-B14E-964878E899AE}"
 EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SourceGen", "SourceGen\SourceGen.csproj", "{E7AD8C00-492F-4C08-96F9-4AF7D2F8D502}"
-EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D8A4235D-18D7-4F89-ABEE-8BC9A5687128}"
 	ProjectSection(SolutionItems) = preProject
 		.editorconfig = .editorconfig
 	EndProjectSection
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ErrorsSourceGen", "ErrorsSourceGen\ErrorsSourceGen.csproj", "{0FA8726B-5737-4983-8922-2CAA8649EAEA}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -22,10 +22,10 @@ Global
 		{49341FFD-B153-419D-B14E-964878E899AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{49341FFD-B153-419D-B14E-964878E899AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{49341FFD-B153-419D-B14E-964878E899AE}.Release|Any CPU.Build.0 = Release|Any CPU
-		{E7AD8C00-492F-4C08-96F9-4AF7D2F8D502}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{E7AD8C00-492F-4C08-96F9-4AF7D2F8D502}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{E7AD8C00-492F-4C08-96F9-4AF7D2F8D502}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{E7AD8C00-492F-4C08-96F9-4AF7D2F8D502}.Release|Any CPU.Build.0 = Release|Any CPU
+		{0FA8726B-5737-4983-8922-2CAA8649EAEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0FA8726B-5737-4983-8922-2CAA8649EAEA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0FA8726B-5737-4983-8922-2CAA8649EAEA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{0FA8726B-5737-4983-8922-2CAA8649EAEA}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/ArbitraryComponentAccess/ArbitraryComponentAccess.csproj b/ArbitraryComponentAccess/ArbitraryComponentAccess.csproj
index 4a223ee..cf3164b 100644
--- a/ArbitraryComponentAccess/ArbitraryComponentAccess.csproj
+++ b/ArbitraryComponentAccess/ArbitraryComponentAccess.csproj
@@ -7,6 +7,7 @@
 		<Deterministic>true</Deterministic>
 		<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
 		<NoWarn>MSB3277</NoWarn>
+		<!-- <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> -->
 	</PropertyGroup>
 
 	<PropertyGroup>
@@ -38,6 +39,9 @@
 		<Reference Include="SkyFrost.Base">
 		  <HintPath>$(ResonitePath)/Resonite_Data/Managed/SkyFrost.Base.dll</HintPath>
 		</Reference>
+		<Reference Include="SkyFrost.Base.Models">
+		  <HintPath>$(ResonitePath)/Resonite_Data/Managed/SkyFrost.Base.Models.dll</HintPath>
+		</Reference>
 	</ItemGroup>
 
 	<ItemGroup>
@@ -45,6 +49,6 @@
 	</ItemGroup>
 
 	<ItemGroup>
-		<ProjectReference Include="..\SourceGen\SourceGen.csproj" OutputItemType="Analyzer" />
+		<ProjectReference Include="..\ErrorsSourceGen\ErrorsSourceGen.csproj" OutputItemType="Analyzer" />
 	</ItemGroup>
 </Project>
diff --git a/ArbitraryComponentAccess/Bindings/ProtoFlux/Components/AddComponent.cs b/ArbitraryComponentAccess/Bindings/ProtoFlux/Components/AddComponent.cs
index f307d38..763c789 100644
--- a/ArbitraryComponentAccess/Bindings/ProtoFlux/Components/AddComponent.cs
+++ b/ArbitraryComponentAccess/Bindings/ProtoFlux/Components/AddComponent.cs
@@ -1,10 +1,11 @@
-﻿using FrooxEngine;
-using ProtoFlux.Core;
+﻿using ProtoFlux.Core;
+using FrooxEngine;
 using FrooxEngine.ProtoFlux;
+using FrooxEngine.ProtoFlux.Runtimes;
 using FrooxEngine.ProtoFlux.Runtimes.Execution;
-using ArbitraryComponentAccess.ProtoFlux.Components;
+using FrooxEngine.ProtoFlux.Runtimes.Execution.Nodes;
 
-using FluxExecutionContext = ProtoFlux.Runtimes.Execution.ExecutionContext;
+using ArbitraryComponentAccess.ProtoFlux.Components;
 
 namespace ArbitraryComponentAccess.ProtoFluxBinds.Components;
 
diff --git a/ArbitraryComponentAccess/ProtoFlux/Components/AddComponent.cs b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/AddComponent.cs
similarity index 98%
rename from ArbitraryComponentAccess/ProtoFlux/Components/AddComponent.cs
rename to ArbitraryComponentAccess/ProtoFlux/ACA/Components/AddComponent.cs
index 1e130f1..bd17549 100644
--- a/ArbitraryComponentAccess/ProtoFlux/Components/AddComponent.cs
+++ b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/AddComponent.cs
@@ -4,15 +4,16 @@
 // shameless theft from https://github.com/ErrorJan/ResonitePlugin-EngineShennanigans/blob/master/EngineShennanigans/ProtoFlux/AddComponent.cs
 // hehe my plugin won the coin flip!!
 
-using ArbitraryComponentAccess.Components;
 using FrooxEngine;
-using FrooxEngine.ProtoFlux;
 using ProtoFlux.Core;
+
+using ArbitraryComponentAccess.Components;
+using FrooxEngine.ProtoFlux;
 using ProtoFlux.Runtimes.Execution;
 
 namespace ArbitraryComponentAccess.ProtoFlux.Components;
 
-[Category("ACA/Components")]
+[NodeCategory("ACA/Components")]
 public class AddComponentLogix : ActionNode<FrooxEngineContext>
 {
     public ObjectInput<Slot> slot;
diff --git a/ArbitraryComponentAccess/ProtoFlux/Components/AddComponent[T].cs b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/AddComponent[T].cs
similarity index 97%
rename from ArbitraryComponentAccess/ProtoFlux/Components/AddComponent[T].cs
rename to ArbitraryComponentAccess/ProtoFlux/ACA/Components/AddComponent[T].cs
index a97b9a9..d86abf2 100644
--- a/ArbitraryComponentAccess/ProtoFlux/Components/AddComponent[T].cs
+++ b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/AddComponent[T].cs
@@ -7,6 +7,7 @@
 
 namespace ArbitraryComponentAccess.ProtoFlux.Components;
 
+[NodeCategory("ACA/Components")]
 public class AddComponentLogix<T> : ActionNode<FrooxEngineContext> where T : Component, new()
 {
     public ObjectInput<Slot> slot;
diff --git a/ArbitraryComponentAccess/ProtoFlux/Components/ComponentFromSlot.cs b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/ComponentFromSlot.cs
similarity index 100%
rename from ArbitraryComponentAccess/ProtoFlux/Components/ComponentFromSlot.cs
rename to ArbitraryComponentAccess/ProtoFlux/ACA/Components/ComponentFromSlot.cs
diff --git a/ArbitraryComponentAccess/ProtoFlux/Components/ComponentFromSlot[T].cs b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/ComponentFromSlot[T].cs
similarity index 100%
rename from ArbitraryComponentAccess/ProtoFlux/Components/ComponentFromSlot[T].cs
rename to ArbitraryComponentAccess/ProtoFlux/ACA/Components/ComponentFromSlot[T].cs
diff --git a/ArbitraryComponentAccess/ProtoFlux/ACA/Components/FindComponentInChildren.cs b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/FindComponentInChildren.cs
new file mode 100644
index 0000000..c964677
--- /dev/null
+++ b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/FindComponentInChildren.cs
@@ -0,0 +1,40 @@
+﻿using ArbitraryComponentAccess.Components;
+using Elements.Core;
+using FrooxEngine;
+using FrooxEngine.ProtoFlux;
+using ProtoFlux.Core;
+using ProtoFlux.Runtimes.Execution;
+
+namespace ArbitraryComponentAccess.ProtoFlux.Components;
+
+[NodeCategory("ACA/Components")]
+public class FindComponentInChildrenLogix : ObjectFunctionNode<FrooxEngineContext, Component>
+{
+    public ObjectInput<Slot> slot;
+    public ObjectInput<Type> componentType;
+    public ValueInput<int> componentIndex;
+    public ValueInput<bool> self;
+
+    protected override Component Compute(FrooxEngineContext context)
+    {
+        Type? ctxType = componentType!.Evaluate(context);
+
+        if (!context.World.Permissions.CheckAll((ACAPermissions p) => p.is_ACA_Allowed))
+        {
+            return null!;
+        }
+        if (ctxType == null || !context.World.Permissions.CheckAll((ACAPermissions p) => p.IsTypeAllowedForExecution( ctxType )))
+        {
+            return null!;
+        }
+
+        Slot? ctxslot = slot!.Evaluate(context);
+        int indx = componentIndex.Evaluate(context);
+        bool ctxself = self.Evaluate(context);
+
+        // handle nulls
+        if (ctxslot == null || ctxslot.IsRemoved ) return null!;
+
+        return ctxslot.GetComponentInChildren<Component>( (c) => c.GetType() == ctxType && indx-- <= 0, ctxself );
+    }
+}
\ No newline at end of file
diff --git a/ArbitraryComponentAccess/ProtoFlux/ACA/Components/FindComponentInChildren[T].cs b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/FindComponentInChildren[T].cs
new file mode 100644
index 0000000..814d839
--- /dev/null
+++ b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/FindComponentInChildren[T].cs
@@ -0,0 +1,37 @@
+﻿using ArbitraryComponentAccess.Components;
+using Elements.Core;
+using FrooxEngine;
+using FrooxEngine.ProtoFlux;
+using ProtoFlux.Core;
+using ProtoFlux.Runtimes.Execution;
+
+namespace ArbitraryComponentAccess.ProtoFlux.Components;
+
+[NodeCategory("ACA/Components")]
+public class FindComponentInChildrenLogix<T> : ObjectFunctionNode<FrooxEngineContext, T> where T : Component
+{
+    public ObjectInput<Slot> slot;
+    public ValueInput<int> componentIndex;
+    public ValueInput<bool> self;
+
+    protected override T Compute(FrooxEngineContext context)
+    {
+        if (!context.World.Permissions.CheckAll((ACAPermissions p) => p.is_ACA_Allowed))
+        {
+            return null!;
+        }
+        if (!context.World.Permissions.CheckAll((ACAPermissions p) => p.IsTypeAllowedForExecution(typeof(T))))
+        {
+            return null!;
+        }
+
+        Slot? ctxslot = slot!.Evaluate(context);
+        int indx = componentIndex.Evaluate(context);
+        bool ctxself = self.Evaluate(context);
+
+        // handle nulls
+        if (ctxslot == null || ctxslot.IsRemoved ) return null!;
+
+        return ctxslot.GetComponentInChildren<T>( (c) => indx-- <= 0, ctxself );
+    }
+}
\ No newline at end of file
diff --git a/ArbitraryComponentAccess/ProtoFlux/ACA/Components/FindComponentInParents.cs b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/FindComponentInParents.cs
new file mode 100644
index 0000000..775dc0a
--- /dev/null
+++ b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/FindComponentInParents.cs
@@ -0,0 +1,40 @@
+﻿using ArbitraryComponentAccess.Components;
+using Elements.Core;
+using FrooxEngine;
+using FrooxEngine.ProtoFlux;
+using ProtoFlux.Core;
+using ProtoFlux.Runtimes.Execution;
+
+namespace ArbitraryComponentAccess.ProtoFlux.Components;
+
+[NodeCategory("ACA/Components")]
+public class FindComponentInParentsLogix : ObjectFunctionNode<FrooxEngineContext, Component>
+{
+    public ObjectInput<Slot> slot;
+    public ObjectInput<Type> componentType;
+    public ValueInput<int> componentIndex;
+    public ValueInput<bool> self;
+
+    protected override Component Compute(FrooxEngineContext context)
+    {
+        Type? ctxType = componentType!.Evaluate(context);
+
+        if (!context.World.Permissions.CheckAll((ACAPermissions p) => p.is_ACA_Allowed))
+        {
+            return null!;
+        }
+        if (ctxType == null || !context.World.Permissions.CheckAll((ACAPermissions p) => p.IsTypeAllowedForExecution( ctxType )))
+        {
+            return null!;
+        }
+
+        Slot? ctxslot = slot!.Evaluate(context);
+        int indx = componentIndex.Evaluate(context);
+        bool ctxself = self.Evaluate(context);
+
+        // handle nulls
+        if (ctxslot == null || ctxslot.IsRemoved ) return null!;
+
+        return ctxslot.GetComponentInParents<Component>( (c) => c.GetType() == ctxType && indx-- <= 0, ctxself );
+    }
+}
\ No newline at end of file
diff --git a/ArbitraryComponentAccess/ProtoFlux/ACA/Components/FindComponentInParents[T].cs b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/FindComponentInParents[T].cs
new file mode 100644
index 0000000..e4b4859
--- /dev/null
+++ b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/FindComponentInParents[T].cs
@@ -0,0 +1,37 @@
+﻿using ArbitraryComponentAccess.Components;
+using Elements.Core;
+using FrooxEngine;
+using FrooxEngine.ProtoFlux;
+using ProtoFlux.Core;
+using ProtoFlux.Runtimes.Execution;
+
+namespace ArbitraryComponentAccess.ProtoFlux.Components;
+
+[NodeCategory("ACA/Components")]
+public class FindComponentInParentsLogix<T> : ObjectFunctionNode<FrooxEngineContext, T> where T : Component
+{
+    public ObjectInput<Slot> slot;
+    public ValueInput<int> componentIndex;
+    public ValueInput<bool> self;
+
+    protected override T Compute(FrooxEngineContext context)
+    {
+        if (!context.World.Permissions.CheckAll((ACAPermissions p) => p.is_ACA_Allowed))
+        {
+            return null!;
+        }
+        if (!context.World.Permissions.CheckAll((ACAPermissions p) => p.IsTypeAllowedForExecution(typeof(T))))
+        {
+            return null!;
+        }
+
+        Slot? ctxslot = slot!.Evaluate(context);
+        int indx = componentIndex.Evaluate(context);
+        bool ctxself = self.Evaluate(context);
+
+        // handle nulls
+        if (ctxslot == null || ctxslot.IsRemoved ) return null!;
+
+        return ctxslot.GetComponentInParents<T>( (c) => indx-- <= 0, ctxself );
+    }
+}
\ No newline at end of file
diff --git a/ArbitraryComponentAccess/ProtoFlux/Components/ForeachComponents.cs b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/ForeachComponents.cs
similarity index 98%
rename from ArbitraryComponentAccess/ProtoFlux/Components/ForeachComponents.cs
rename to ArbitraryComponentAccess/ProtoFlux/ACA/Components/ForeachComponents.cs
index 51ea57c..3c4317d 100644
--- a/ArbitraryComponentAccess/ProtoFlux/Components/ForeachComponents.cs
+++ b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/ForeachComponents.cs
@@ -7,6 +7,7 @@
 
 namespace ArbitraryComponentAccess.ProtoFlux.Components;
 
+[NodeCategory("ACA/Components")]
 public class ForeachComponentLogix : ActionNode<FrooxEngineContext>
 {
     public ObjectInput<Slot> slot;
diff --git a/ArbitraryComponentAccess/ProtoFlux/Components/RemoveComponent.cs b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/RemoveComponent.cs
similarity index 97%
rename from ArbitraryComponentAccess/ProtoFlux/Components/RemoveComponent.cs
rename to ArbitraryComponentAccess/ProtoFlux/ACA/Components/RemoveComponent.cs
index 1b0f82d..5987ec6 100644
--- a/ArbitraryComponentAccess/ProtoFlux/Components/RemoveComponent.cs
+++ b/ArbitraryComponentAccess/ProtoFlux/ACA/Components/RemoveComponent.cs
@@ -12,7 +12,7 @@
 
 namespace ArbitraryComponentAccess.ProtoFlux.Components;
 
-[Category("ACA/Components")]
+[NodeCategory("ACA/Components")]
 public class RemoveComponentLogix : ActionNode<FrooxEngineContext>
 {
     public ObjectInput<Component> component;
diff --git a/ArbitraryComponentAccess/ProtoFlux/Fields/FieldFromComponent.cs b/ArbitraryComponentAccess/ProtoFlux/ACA/Fields/FieldFromComponent.cs
similarity index 100%
rename from ArbitraryComponentAccess/ProtoFlux/Fields/FieldFromComponent.cs
rename to ArbitraryComponentAccess/ProtoFlux/ACA/Fields/FieldFromComponent.cs
diff --git a/ArbitraryComponentAccess/ProtoFlux/ACA/Fields/FieldToString.cs b/ArbitraryComponentAccess/ProtoFlux/ACA/Fields/FieldToString.cs
new file mode 100644
index 0000000..80d2e42
--- /dev/null
+++ b/ArbitraryComponentAccess/ProtoFlux/ACA/Fields/FieldToString.cs
@@ -0,0 +1,27 @@
+﻿using FrooxEngine;
+using FrooxEngine.ProtoFlux;
+using ProtoFlux.Core;
+using ProtoFlux.Runtimes.Execution;
+
+namespace ArbitraryComponentAccess.ProtoFlux.Fields;
+
+[NodeCategory("ACA/Fields")]
+public class FieldToStringLogix : ObjectFunctionNode<FrooxEngineContext, string>
+{
+    public ObjectInput<IField<string>> field;
+
+    protected override string Compute(FrooxEngineContext context)
+    {
+        IField? field = this.field!.Evaluate(context);
+
+        if (field == null) 
+            return default!;
+
+        if (field.BoxedValue is string t)
+        {
+            return t;
+        }
+
+        return default!;
+    }
+}
\ No newline at end of file
diff --git a/ArbitraryComponentAccess/ProtoFlux/Fields/FieldToValue.cs b/ArbitraryComponentAccess/ProtoFlux/ACA/Fields/FieldToValue.cs
similarity index 100%
rename from ArbitraryComponentAccess/ProtoFlux/Fields/FieldToValue.cs
rename to ArbitraryComponentAccess/ProtoFlux/ACA/Fields/FieldToValue.cs
diff --git a/ArbitraryComponentAccess/ProtoFlux/EngineShennanigans/CloudSpawn.cs b/ArbitraryComponentAccess/ProtoFlux/EngineShennanigans/CloudSpawn.cs
new file mode 100644
index 0000000..7df22ae
--- /dev/null
+++ b/ArbitraryComponentAccess/ProtoFlux/EngineShennanigans/CloudSpawn.cs
@@ -0,0 +1,69 @@
+using FrooxEngine;
+using FrooxEngine.ProtoFlux;
+
+using ProtoFlux.Core;
+using ProtoFlux.Runtimes.Execution;
+
+using Elements.Core;
+
+namespace ArbitraryComponentAccess.ProtoFlux.Components;
+
+// Revive of EngineShennanigans POG?
+[NodeCategory("EngineShennanigans")]
+public class CloudSpawnLogix : AsyncActionNode<FrooxEngineContext>
+{
+    public ObjectInput<Uri> recordURL;
+    public ValueInput<float3> spawnPos;
+    public ValueInput<floatQ> spawnRot;
+    public ValueInput<float3> spawnScl;
+    public ValueInput<bool> spawnPersistant;
+    public ValueInput<bool> multiplyWithSavedScale;
+    public ObjectInput<Slot> spawnParent;
+    public readonly ObjectOutput<Slot> spawnedSlot;
+    public AsyncCall onStartedSpawn;
+    public Continuation onSpawned;
+    public Continuation onFailed;
+
+    public CloudSpawnLogix()
+    {
+        spawnedSlot = new(this);
+    }
+
+    protected override async Task<IOperation> RunAsync( FrooxEngineContext ctx )
+    {
+        await onStartedSpawn.ExecuteAsync( ctx );
+
+        Uri? recordURL = this.recordURL!.Evaluate( ctx );
+        Slot spawnParent = this.spawnParent!.Evaluate( ctx ) ?? ctx.World.RootSlot;
+        float3 spawnPos = this.spawnPos.Evaluate( ctx );
+        floatQ spawnRot = this.spawnRot.Evaluate( ctx );
+        float3 spawnScl = this.spawnScl.Evaluate( ctx );
+        bool spawnPersistant = this.spawnPersistant.Evaluate( ctx, true );
+        bool multiplyWithSavedScale = this.multiplyWithSavedScale.Evaluate( ctx, true );
+        
+        if ( recordURL == null )
+            return onFailed.Target;
+
+        Slot slot = spawnParent.AddSlot( "Cloud Spawned", spawnPersistant );
+        bool ok = await slot.LoadObjectAsync( recordURL, skipHolder: true );
+
+        if ( multiplyWithSavedScale )
+            slot.LocalScale *= spawnScl;
+        else
+            slot.LocalScale = spawnScl;
+
+        slot.LocalPosition = spawnPos;
+        slot.LocalRotation = spawnRot;
+
+        if ( !ok )
+        {
+            slot.Destroy();
+            spawnedSlot.Write( null!, ctx );
+            return onFailed.Target;
+        }
+
+        spawnedSlot.Write( slot, ctx );
+
+        return onSpawned.Target;
+    }
+}
\ No newline at end of file
diff --git a/ArbitraryComponentAccess/ProtoFlux/Slots/ForeachChildSlot.cs b/ArbitraryComponentAccess/ProtoFlux/EngineShennanigans/ForeachChildSlot.cs
similarity index 96%
rename from ArbitraryComponentAccess/ProtoFlux/Slots/ForeachChildSlot.cs
rename to ArbitraryComponentAccess/ProtoFlux/EngineShennanigans/ForeachChildSlot.cs
index 3736de7..b60e4b1 100644
--- a/ArbitraryComponentAccess/ProtoFlux/Slots/ForeachChildSlot.cs
+++ b/ArbitraryComponentAccess/ProtoFlux/EngineShennanigans/ForeachChildSlot.cs
@@ -6,6 +6,8 @@
 
 namespace ArbitraryComponentAccess.ProtoFlux.Components;
 
+// Revive of EngineShennanigans POG?
+[NodeCategory("EngineShennanigans")]
 public class ForeachChildSlotLogix : ActionNode<FrooxEngineContext>
 {
     public ObjectInput<Slot> slot;
diff --git a/ErrorsSourceGen/ErrorsSourceGen.cs b/ErrorsSourceGen/ErrorsSourceGen.cs
new file mode 100644
index 0000000..36f6348
--- /dev/null
+++ b/ErrorsSourceGen/ErrorsSourceGen.cs
@@ -0,0 +1,334 @@
+﻿/////////////////////////////////////
+// ErrorJan's FluxBindingsGen      //
+// MIT License                     //
+/////////////////////////////////////
+
+using System;
+using System.Linq;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace ErrorsSourceGen;
+
+[ Generator( LanguageNames.CSharp ) ]
+public class FluxBindings : IIncrementalGenerator
+{
+    // #pragma warning disable RS1035
+    // // Fuck you, I need to LOG SHIT FOR DEBUGGING PLEASE
+    // private static readonly string logFilePath = System.IO.Path.Combine(
+    //     System.IO.Directory.GetCurrentDirectory(),
+    //     "generator_debug_log.txt");
+
+    // private static void LogMessage(string message)
+    // {
+    //     try
+    //     {
+    //         // Append the message to the log file
+    //         using (var writer = new System.IO.StreamWriter(logFilePath, true))
+    //         {
+    //             writer.AutoFlush = true;
+    //             writer.WriteLine($"{DateTime.Now}: {message}");
+    //             writer.Flush();
+    //         }
+    //     }
+    //     catch (Exception) {}
+    // }
+    // private static void ClearLog()
+    // {
+    //     try
+    //     {
+    //         // Append the message to the log file
+    //         using (var writer = new System.IO.StreamWriter(logFilePath, false))
+    //         {
+    //             writer.AutoFlush = true;
+    //             writer.WriteLine($"{DateTime.Now}: Cleared!");
+    //             writer.Flush();
+    //         }
+    //     }
+    //     catch (Exception) {}
+    // }
+    // private static void PrintList( System.Collections.IEnumerable objs )
+    // {
+    //     foreach ( var obj in objs )
+    //         LogMessage( obj.ToString() );
+    // }
+    // #pragma warning restore RS1035
+
+    public void Initialize( IncrementalGeneratorInitializationContext context )
+    {
+        IncrementalValuesProvider<GeneratorSyntaxContext> allClasses = context.SyntaxProvider.CreateSyntaxProvider( 
+            ( syntaxNode, _ ) => syntaxNode is ClassDeclarationSyntax node,
+            ( generatorSyntaxContext, _  ) => generatorSyntaxContext
+        );
+
+        IncrementalValuesProvider<GeneratorSyntaxContext> allProtoFluxImplementationClasses = allClasses.Where( IsProtoFluxImplementClass );
+
+        context.RegisterSourceOutput( allProtoFluxImplementationClasses, GenSource );
+    }
+
+    private string GetFormattedTypeName( INamedTypeSymbol typeSymbol )
+    {
+        string typeName = typeSymbol.Name;
+        typeName = typeName.Remove( typeName.IndexOf( "Logix" ) );
+
+        if ( typeSymbol.IsGenericType )
+        {
+            // Construct the type name with generic parameters
+            string genericArgs = string.Join( ", ", typeSymbol.TypeParameters.Select( tp => tp.Name ) );
+            return $"{ typeName }<{ genericArgs }>";
+        }
+        else
+        {
+            return typeName;
+        }
+    }
+
+
+    private void GenSource( SourceProductionContext context, GeneratorSyntaxContext nodeMeta )
+    {
+        INamedTypeSymbol classSymbol = (nodeMeta.SemanticModel.GetDeclaredSymbol( nodeMeta.Node ) as INamedTypeSymbol)!;
+        string bindingNamespace = $"FluxBinding.{classSymbol.ContainingNamespace}";
+        string nodeCategory = "ACA/Uncategorized";
+        string className = GetFormattedTypeName( classSymbol );
+        string genericArgs = string.Join( ", ", classSymbol.BaseType?.TypeArguments.Select( 
+            arg => arg.ToString().Contains( "Context" ) ? "global::" + arg.ToString() : arg.ToString() ) );
+        string constraints = string.Join( " ", classSymbol.TypeParameters
+            .Where( tp => tp.ConstraintTypes.Length > 0 || tp.HasConstructorConstraint || tp.HasUnmanagedTypeConstraint )
+            .Select( tp => $"where { tp.Name } : { string.Join( ", ", tp.ConstraintTypes.Select( c => c.ToString() )
+                .Concat( [ 
+                    tp.HasConstructorConstraint ? "new()" : null, 
+                    tp.HasUnmanagedTypeConstraint ? "unmanaged" : null ] )
+                .Where( (s) => s is not null ) 
+            ) }" )
+            .ToList() );
+        string fullClassName = classSymbol.ToString();
+        string inputSyncRefsDecl = "\n";
+        string inputSyncRefsGets = "";
+        int inputSyncRefAmount = 0;
+        string outputRefsDecl = "";
+        string outputRefsGets = "";
+        int outputRefAmount = 0;
+        string callSyncRefsDecl = "";
+        string callSyncRefsGets = "";
+        int callSyncRefAmount = 0;
+
+        foreach ( var att in classSymbol.GetAttributes() )
+        {
+            try
+            {
+                // If exception, then most likely this died.. Make sure to use NodeCategory and not Category!!
+                var arg = att.ConstructorArguments.FirstOrDefault().Value;
+                if ( att.AttributeClass?.Name == "NodeCategoryAttribute" && arg != null )
+                {
+                    nodeCategory = arg.ToString();
+                    break;
+                }
+            }
+            catch( Exception ) 
+            {
+                return;
+            }
+        }
+
+        var fields = classSymbol.GetMembers().OfType<IFieldSymbol>();
+        foreach ( IFieldSymbol field in fields )
+        {
+            if ( field.IsStatic || field.DeclaredAccessibility != Accessibility.Public )
+                continue;
+            
+            if ( field.Type is INamedTypeSymbol fieldType2 )
+            {
+                string constructedField = "    public readonly {0} {1} = new();";
+                string constructedType;
+                string typeArgs = string.Join( ", ", fieldType2.TypeArguments );
+
+                switch( field.Type.Name )
+                {
+                    // ---- Inputs ----
+                    case "ObjectInput":
+                        string nodeOutputType = "INodeObjectOutput";    
+                        goto ContinueInput;
+                    case "ValueInput":
+                        nodeOutputType = "INodeValueOutput";
+                    
+                    ContinueInput:
+                        constructedType = $"SyncRef<{ nodeOutputType }<{ typeArgs }>>";
+                        string fieldDecl = string.Format( constructedField, constructedType, field.Name );
+                        inputSyncRefsDecl += fieldDecl + "\n";
+                        inputSyncRefsGets += $"        case {inputSyncRefAmount++}: return {field.Name};\n";
+                        break;
+
+                    // ---- Outputs ----
+                    case "ObjectOutput":
+                        nodeOutputType = "NodeObjectOutput";
+                        goto ContinueOutput;
+                    case "ValueOutput":
+                        nodeOutputType = "NodeValueOutput";
+
+                    ContinueOutput:
+                        constructedType = $"{ nodeOutputType }<{ typeArgs }>";
+                        fieldDecl = string.Format( constructedField, constructedType, field.Name );
+                        outputRefsDecl += fieldDecl + "\n";
+                        outputRefsGets += $"        case {outputRefAmount++}: return {field.Name};\n";
+                        break;
+
+                    // ---- Calls ----
+                    case "Call":
+                        nodeOutputType = "ISyncNodeOperation";
+                        goto ContinueCalls;
+                    case "Continuation":
+                    case "AsyncCall":
+                        nodeOutputType = "INodeOperation";
+
+                    ContinueCalls:
+                        constructedType = $"SyncRef<{ nodeOutputType }>";
+                        fieldDecl = string.Format( constructedField, constructedType, field.Name );
+                        callSyncRefsDecl += fieldDecl + "\n";
+                        callSyncRefsGets += $"        case {callSyncRefAmount++}: return {field.Name};\n";
+                        break;
+
+                    default:
+                        continue;
+                }
+            }
+            else
+                return;
+        }
+
+        string templateCode = 
+$$"""
+using ProtoFlux.Core;
+using FrooxEngine;
+using FrooxEngine.ProtoFlux;
+using FrooxEngine.ProtoFlux.Runtimes;
+using FrooxEngine.ProtoFlux.Runtimes.Execution;
+using FrooxEngine.ProtoFlux.Runtimes.Execution.Nodes;
+
+namespace {{ bindingNamespace }};
+
+[Category( "ProtoFlux/Runtimes/Execution/Nodes/{{ nodeCategory }}" )]
+public class {{className}} : {{classSymbol.BaseType!.Name}}<{{genericArgs}}> {{constraints}}
+{
+    public global::{{fullClassName}} TypedNodeInstance { get; private set; } = null!;
+    public override Type NodeType => typeof( global::{{fullClassName}} );
+    public override INode NodeInstance => TypedNodeInstance!;
+
+{{inputSyncRefsDecl.Remove(inputSyncRefsDecl.Length - 1)}}
+    public override int NodeInputCount => base.NodeInputCount + {{inputSyncRefAmount}};
+{{outputRefsDecl}}
+    public override int NodeOutputCount => base.NodeOutputCount + {{outputRefAmount}};
+{{callSyncRefsDecl}}
+    public override int NodeImpulseCount => base.NodeImpulseCount + {{callSyncRefAmount}};
+
+    public override void ClearInstance()
+    {
+        TypedNodeInstance = null!;
+    }
+
+    public override N Instantiate<N>()
+    {
+        if ( TypedNodeInstance != null )
+        {
+            throw new InvalidOperationException( "Node has already been instantiated" );
+        }
+
+        TypedNodeInstance = new global::{{fullClassName}}();
+        return (TypedNodeInstance as N)!;
+    }
+
+    protected override void AssociateInstanceInternal( INode node )
+    {
+        if ( node is global::{{fullClassName}} typedNodeInstance )
+        {
+            TypedNodeInstance = typedNodeInstance;
+            return;
+        }
+        throw new ArgumentException( "Node instance is not of type " + typeof( global::{{fullClassName}} ) );
+    }
+
+    protected override ISyncRef GetInputInternal( ref int index )
+    {
+        ISyncRef inputInternal = base.GetInputInternal( ref index );
+        if ( inputInternal != null )
+        {
+            return inputInternal;
+        }
+
+        switch ( index )
+        {
+{{inputSyncRefsGets}}
+        default:
+            index -= {{inputSyncRefAmount}};
+            return null!;
+        }
+    }
+
+    protected override INodeOutput GetOutputInternal( ref int index )
+    {
+        INodeOutput outputInternal = base.GetOutputInternal( ref index );
+        if ( outputInternal != null )
+        {
+            return outputInternal;
+        }
+
+        switch ( index )
+        {
+{{outputRefsGets}}
+        default:
+            index -= {{outputRefAmount}};
+            return null!;
+        }
+    }
+
+    protected override ISyncRef GetImpulseInternal( ref int index )
+    {
+        ISyncRef impulseInternal = base.GetImpulseInternal( ref index );
+        if ( impulseInternal != null )
+        {
+            return impulseInternal;
+        }
+        switch ( index )
+        {
+{{callSyncRefsGets}}
+        default:
+            index -= {{callSyncRefAmount}};
+            return null!;
+        }
+    }
+}
+""";
+
+        string classSymbolText = classSymbol.ToString().Replace('<', '[').Replace('>', ']');
+        context.AddSource( $"FluxBinding.{classSymbolText}.g.cs", templateCode );
+    }
+
+    private bool IsProtoFluxImplementClass( GeneratorSyntaxContext nodeMeta )
+    {
+        string firstLine = nodeMeta.Node.SyntaxTree.GetText().Lines.First().ToString().ToLower();
+        if ( firstLine.Contains( "no auto" ) || firstLine.Contains( "noauto" ) )
+            return false;
+
+        // Since our Node is of type ClassDeclarationSyntax, GetDeclaredSymbol will give us INamedTypeSymbol
+        // https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.csharp.csharpextensions.getdeclaredsymbol?view=roslyn-dotnet-4.9.0#microsoft-codeanalysis-csharp-csharpextensions-getdeclaredsymbol(microsoft-codeanalysis-semanticmodel-microsoft-codeanalysis-csharp-syntax-basetypedeclarationsyntax-system-threading-cancellationtoken)
+        INamedTypeSymbol classSymbol = (nodeMeta.SemanticModel.GetDeclaredSymbol( nodeMeta.Node ) as INamedTypeSymbol)!;
+
+        // Iterate through the interfaces and print their fully qualified names
+        foreach ( INamedTypeSymbol i in classSymbol.AllInterfaces )
+        {
+            if ( i.Name == "INode" && i.ContainingNamespace.ToString() == "ProtoFlux.Core" )
+                return true;
+        }
+
+        // Traverse base types to check inheritance
+        // INamedTypeSymbol? baseType = classSymbol.BaseType;
+        // while ( baseType != null )
+        // {
+        //     if ( baseType.Name == "Node" && baseType.ContainingNamespace.ToString() == "ProtoFlux.Core" )
+        //         return true;
+
+        //     baseType = baseType.BaseType;
+        // }
+
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/ErrorsSourceGen/ErrorsSourceGen.csproj b/ErrorsSourceGen/ErrorsSourceGen.csproj
new file mode 100644
index 0000000..9bb7456
--- /dev/null
+++ b/ErrorsSourceGen/ErrorsSourceGen.csproj
@@ -0,0 +1,13 @@
+﻿<Project Sdk="Microsoft.NET.Sdk">
+    <PropertyGroup>
+        <TargetFramework>netstandard2.0</TargetFramework>
+        <LangVersion>latest</LangVersion>
+        <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
+        <Nullable>enable</Nullable>
+    </PropertyGroup>
+
+    <ItemGroup>
+        <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
+        <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
+    </ItemGroup>
+</Project>
diff --git a/SourceGen/BindingGenerator.cs b/SourceGen/BindingGenerator.cs
deleted file mode 100644
index 544da3c..0000000
--- a/SourceGen/BindingGenerator.cs
+++ /dev/null
@@ -1,383 +0,0 @@
-﻿//////////////////////////////////////////////////////////////////////////////////////////////////
-// THIS CODE IS FROM https://github.com/Xlinka/Project-Obsidian/                                //
-// BY XLINKA AND OTHER CONTRIBUTORS.                                                            //
-// DISTRIBUTED UNDER GPL-3.0                                                                    //
-// PLEASE SEE https://github.com/Xlinka/Project-Obsidian/blob/main/LICENSE FOR MORE INFORMATION //
-//                                                                                              //
-// CHANGELOG                                                                                    //
-// - added option to prevent generator from running by adding "// no auto" anywhere in a file   //
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-
-namespace SourceGenerators
-{
-    public static class StringHelpers
-    {
-        public static string TrimEnds(this string str, int fromStart, int fromEnd) =>
-            str.Substring(fromStart, str.Length - fromEnd - fromStart);
-    }
-    [Generator]
-    public class BindingGenerator : ISourceGenerator
-    {
-        public void Initialize(GeneratorInitializationContext context)
-        {
-        }
-
-        public void Execute(GeneratorExecutionContext context)
-        {
-            foreach (var tree in context.Compilation.SyntaxTrees)
-            {
-                var src_txt = tree.GetText();
-                var muted_txt = src_txt.ToString();
-
-                var array_of_txt = muted_txt.Split(
-                    new string[] {"\r\n"},
-                    StringSplitOptions.None
-                    );
-
-                if (array_of_txt[0].ToLower().Contains("// no auto"))
-                    continue;
-
-                var result = new StringBuilder();
-                var root = tree.GetCompilationUnitRoot();
-                var walker = new BindingGeneratorSyntaxWalker();
-                walker.Visit(root);
-                result.Append(walker.Result);
-
-                var res = result.ToString();
-
-                if (!string.IsNullOrWhiteSpace(res))
-                    context.AddSource($"{walker.BaseName}Bindings.g.cs", result.ToString());
-            }
-        }
-    }
-
-    public class BindingGeneratorSyntaxWalker : CSharpSyntaxWalker
-    {
-        private class OrderedCount
-        {
-            private readonly string CountVariableName;
-            private readonly string MethodName;
-            private readonly string MethodReturnType;
-            public string CountOverride => VariableNames.Count == 0
-                ? ""
-                : $"    public override int {CountVariableName} => base.{CountVariableName} + {VariableNames.Count};\n";
-
-            public void Add(string value) => VariableNames.Add(value);
-
-            public string GetOverride
-            {
-                get
-                {
-                    if (VariableNames.Count == 0) return "";
-                    var str = $@"
-    protected override {MethodReturnType} {MethodName}(ref int index)
-    {{
-        var item = base.{MethodName}(ref index);
-        if (item != null) return item;
-        switch (index)
-        {{
-";
-                    for (var index = 0; index < VariableNames.Count; index++)
-                    {
-                        var order = VariableNames[index];
-                        str += $"            case {index}:\n                return this.{order};\n";
-                    }
-                    str += $@"
-            default:
-                index -= {VariableNames.Count};
-                return null;
-        }}
-    }}";
-                    return str;
-                }
-            }
-
-            public readonly List<string> VariableNames = new();
-
-            public OrderedCount(string countVariableName, string methodName, string methodReturnType)
-            {
-                CountVariableName = countVariableName;
-                MethodName = methodName;
-                MethodReturnType = methodReturnType;
-            }
-        }
-
-        public const string BindingPrefix = "FrooxEngine.";
-        public const string FluxPrefix = "ProtoFlux.Runtimes.Execution.";
-
-        //TODO: add more, this is not all of the valid node types
-        public static readonly string[] ValidNodeTypes =
-        {
-            "NestedNode",
-            "VoidNode",
-
-            "ObjectFunctionNode",
-            "ValueFunctionNode",
-
-            "ActionNode",
-            "ActionFlowNode",
-            "ActionBreakableFlowNode",
-
-            "AsyncActionNode",
-            "AsyncActionFlowNode",
-            "AsyncActionBreakableFlowNode",
-        };
-
-        private string UsingEnumerate =>
-            _usingDeclarations
-                .Where(u => !string.IsNullOrWhiteSpace(u))
-                .Aggregate("", (current, u) => current + $"using {u};\n");
-
-        private readonly OrderedCount _inputCount = new("NodeInputCount", "GetInputInternal", "ISyncRef");
-        private readonly OrderedCount _outputCount = new("NodeOutputCount", "GetOutputInternal", "INodeOutput");
-        private readonly OrderedCount _impulseCount = new("NodeImpulseCount", "GetImpulseInternal", "ISyncRef");
-        private readonly OrderedCount _operationCount = new("NodeOperationCount", "GetOperationInternal", "INodeOperation");
-        private readonly OrderedCount _globalRefCount = new("NodeGlobalRefCount", "GetGlobalRefInternal", "ISyncRef");
-
-        private readonly OrderedCount _inputListCount = new("NodeInputListCount", "GetInputListInternal", "ISyncList");
-        private readonly OrderedCount _outputListCount = new("NodeOutputListCount", "GetOutputListInternal", "ISyncList");
-        private readonly OrderedCount _impulseListCount = new("NodeImpulseListCount", "GetImpulseListInternal", "ISyncList");
-        private readonly OrderedCount _operationListCount = new("NodeOperationListCount", "GetOperationListInternal", "ISyncList");
-
-        private IEnumerable<OrderedCount> _counts => new[]
-            { _inputCount, _outputCount, _impulseCount, _operationCount, _globalRefCount,
-                _inputListCount, _outputListCount, _impulseListCount, _operationListCount };
-
-        private string CountOverride => string.Concat(_counts.Select(i => i.CountOverride));
-        private string GetOverride => string.Concat(_counts.Select(i => i.GetOverride));
-
-        private List<string> _declarations = [];
-        private string Declarations => string.Concat(_declarations);
-
-        public string Result
-        {
-            get
-            {
-                if (!_valid) return "";
-
-                var str = @$"//generated
-{UsingEnumerate}
-using {_currentNameSpace};
-
-namespace {BindingPrefix}{_currentNameSpace};
-
-{_genericTypesAttribute}
-{_oldTypeNameAttribute}
-[Category(new string[] {{""ProtoFlux/Runtimes/Execution/Nodes/{_category}""}})]
-public partial class {_fullName} : global::FrooxEngine.ProtoFlux.Runtimes.Execution.{_baseType} {_constraints}
-{{
-{(string.IsNullOrEmpty(_debug) ? "" : "//")}{_debug}
-{Declarations}
-{_nodeNameOverride}
-{(_isValidGenericTypeMethod ? $"    public static bool IsValidGenericType => global::{_currentNameSpace}.{_fullName}.IsValidGenericType;" : "")}
-    public override System.Type NodeType => typeof (global::{_currentNameSpace}.{_fullName});
-    public global::{_currentNameSpace}.{_fullName} TypedNodeInstance {{ get; private set; }}
-    public override INode NodeInstance => (INode)this.TypedNodeInstance;
-    public override void ClearInstance() => this.TypedNodeInstance = null;
-{CountOverride}
-    public override N Instantiate<N>()
-    {{
-        if (this.TypedNodeInstance != null) throw new System.InvalidOperationException(""Node has already been instantiated"");
-        var localVar = new global::{_currentNameSpace}.{_fullName}();
-        this.TypedNodeInstance = localVar;
-        return localVar as N;
-    }}
-    protected override void AssociateInstanceInternal(INode node) => this.TypedNodeInstance = node is global::{_currentNameSpace}.{_fullName} localVar ? localVar : throw new System.ArgumentException(""Node instance is not of type "" + typeof (global::{_currentNameSpace}.{_fullName})?.ToString());
-{GetOverride}
-}}";
-                return str;
-            }
-        }
-
-        private readonly List<string> _usingDeclarations = [""];
-        private bool _valid;
-        private string _currentNameSpace;
-        private string _fullName;
-        private string _additionalName = "";
-        public string BaseName;
-        private string _baseType;
-        private string _fullBaseType;
-        private string _match;
-        private string _category;
-        private string _nodeNameOverride = "";
-        private string _debug = "";
-        private bool _isValidGenericTypeMethod;
-        private string _constraints = "";
-        private string _genericTypesAttribute;
-        private string _oldTypeNameAttribute;
-
-        private bool TypedFieldDetection(string type, string name, string targetTypeName, string declarationFormat, OrderedCount counter)
-        {
-            if (!type.Contains(targetTypeName)) return false;
-            var t = type.TrimEnds((targetTypeName + "<").Length, 1);
-            counter.Add(name);
-            _declarations.Add(string.Format("    new public readonly " + declarationFormat + " {0};\n", name, t));
-            return true;
-        }
-        private bool UntypedFieldDetection(string type, string name, string targetTypeName, string declarationFormat, OrderedCount counter)
-        {
-            if (!type.Contains(targetTypeName)) return false;
-            counter.Add(name);
-            _declarations.Add(string.Format("    new public readonly " + declarationFormat + " {0};\n", name));
-            return true;
-        }
-        public override void VisitFieldDeclaration(FieldDeclarationSyntax node)
-        {
-            var type = node.Declaration.Type.ToString();
-            var name = node.Declaration.Variables.First().ToString();
-
-            //inputs
-            TypedFieldDetection(type, name, "ObjectInput", "global::FrooxEngine.SyncRef<global::FrooxEngine.ProtoFlux.INodeObjectOutput<{1}>>", _inputCount);
-            TypedFieldDetection(type, name, "ObjectArgument", "global::FrooxEngine.SyncRef<global::FrooxEngine.ProtoFlux.INodeObjectOutput<{1}>>", _inputCount);
-            TypedFieldDetection(type, name, "ValueInput", "global::FrooxEngine.SyncRef<global::FrooxEngine.ProtoFlux.INodeValueOutput<{1}>>", _inputCount);
-            TypedFieldDetection(type, name, "ValueArgument", "global::FrooxEngine.SyncRef<global::FrooxEngine.ProtoFlux.INodeValueOutput<{1}>>", _inputCount);
-
-            //outputs
-            TypedFieldDetection(type, name, "ObjectOutput", "global::FrooxEngine.ProtoFlux.NodeObjectOutput<{1}>", _outputCount);
-            TypedFieldDetection(type, name, "ValueOutput", "global::FrooxEngine.ProtoFlux.NodeValueOutput<{1}>", _outputCount);
-
-            //impulses
-            if (!UntypedFieldDetection(type, name, "AsyncCall", "global::FrooxEngine.SyncRef<global::FrooxEngine.ProtoFlux.INodeOperation>", _impulseCount))
-                UntypedFieldDetection(type, name, "Call", "global::FrooxEngine.SyncRef<global::FrooxEngine.ProtoFlux.ISyncNodeOperation>", _impulseCount);
-            UntypedFieldDetection(type, name, "Continuation", "global::FrooxEngine.SyncRef<global::FrooxEngine.ProtoFlux.INodeOperation>", _impulseCount);
-            UntypedFieldDetection(type, name, "AsyncResumption", "global::FrooxEngine.SyncRef<global::FrooxEngine.ProtoFlux.INodeOperation>", _impulseCount);
-
-            //global refs
-            TypedFieldDetection(type, name, "GlobalRef", "global::FrooxEngine.SyncRef<global::FrooxEngine.ProtoFlux.IGlobalValueProxy<{1}>>", _globalRefCount);
-
-            //operations
-            UntypedFieldDetection(type, name, "Operation", "global::FrooxEngine.ProtoFlux.SyncNodeOperation", _operationCount);
-
-            //lists
-
-            //input lists
-            TypedFieldDetection(type, name, "ValueInputList", "global::FrooxEngine.SyncRefList<global::FrooxEngine.ProtoFlux.INodeValueOutput<{1}>>", _inputListCount);
-
-            //output lists
-            TypedFieldDetection(type, name, "ObjectInputList", "global::FrooxEngine.SyncRefList<global::FrooxEngine.ProtoFlux.INodeObjectOutput<{1}>>", _outputListCount);
-
-            //impulse lists
-            UntypedFieldDetection(type, name, "ContinuationList", "global::FrooxEngine.SyncRefList<global::FrooxEngine.ProtoFlux.INodeOperation>", _impulseListCount);
-
-            //operation lists
-            UntypedFieldDetection(type, name, "SyncOperationList", "global::FrooxEngine.SyncList<global::FrooxEngine.ProtoFlux.SyncNodeOperation>", _operationListCount);
-
-            base.VisitFieldDeclaration(node);
-        }
-        public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node)
-        {
-            if (node.Identifier.ValueText.Contains("IsValidGenericType")) _isValidGenericTypeMethod = true;
-            base.VisitPropertyDeclaration(node);
-
-        }
-        public override void VisitNamespaceDeclaration(NamespaceDeclarationSyntax node)
-        {
-            _currentNameSpace = node.Name.ToString();
-            base.VisitNamespaceDeclaration(node);
-        }
-
-        public override void VisitFileScopedNamespaceDeclaration(FileScopedNamespaceDeclarationSyntax node)
-        {
-            _currentNameSpace = node.Name.ToString();
-            base.VisitFileScopedNamespaceDeclaration(node);
-        }
-
-        public override void VisitUsingDirective(UsingDirectiveSyntax node)
-        {
-            if (node.Name is not null) _usingDeclarations.Add(node.Name.ToString());
-            base.VisitUsingDirective(node);
-        }
-        public override void VisitClassDeclaration(ClassDeclarationSyntax node)
-        {
-            if (node.BaseList is null)
-            {
-                base.VisitClassDeclaration(node);
-                return;
-            }
-
-            var baseName = node.Identifier.Text;
-            var fullName = baseName;
-
-            if (node.TypeParameterList is not null)
-            {
-                _additionalName += "<";
-                _additionalName = node.TypeParameterList.Parameters.Aggregate(_additionalName,
-                    (current, p) => current + $"{p.Identifier.Text},");
-                _additionalName = _additionalName.Substring(0, _additionalName.Length - 1); //remove last ,
-                _additionalName += ">";
-
-                fullName += _additionalName;
-            }
-
-            BaseName = baseName;
-            _fullName = fullName;
-
-            if (node.ConstraintClauses.Any())
-            {
-                _constraints = node.ConstraintClauses.ToString();
-            }
-
-            var firstBaseType = node.BaseList.Types.First();
-            var baseTypeName = firstBaseType.Type.ToString();
-
-            _baseType = baseTypeName;
-
-            if (!node.AttributeLists.Any())
-            {
-                base.VisitClassDeclaration(node);
-                return;
-            }
-
-            var find = node.AttributeLists.SelectMany(i => i.Attributes)
-                .FirstOrDefault(i => i.Name.ToString() == "NodeCategory");
-
-            _genericTypesAttribute = node.AttributeLists.FirstOrDefault(attrList => attrList.Attributes.Any(attr => attr.Name.ToString() == "GenericTypes"))?.ToString();
-
-            _oldTypeNameAttribute = node.AttributeLists.FirstOrDefault(attrList => attrList.Attributes.Any(attr => attr.Name.ToString() == "OldTypeName"))?.ToString();
-
-            if (find?.ArgumentList is null)
-            {
-                base.VisitClassDeclaration(node);
-                return;
-            }
-
-            _category = find.ArgumentList.Arguments.First().ToString().TrimEnds(1, 1);
-
-            var findName = node.AttributeLists.SelectMany(i => i.Attributes)
-                .FirstOrDefault(i => i.Name.ToString() == "NodeName");
-
-
-            if (findName?.ArgumentList != null)
-                _nodeNameOverride =
-                    $"    public override string NodeName => {findName.ArgumentList.Arguments.First().ToString()};";
-
-            foreach (var u in _usingDeclarations)
-            {
-                var fullNameSpace = "";
-                if (string.IsNullOrEmpty(u))
-                    fullNameSpace = baseTypeName;
-                else
-                    fullNameSpace = u + "." + baseTypeName;
-
-                var match = ValidNodeTypes.FirstOrDefault(i => fullNameSpace.StartsWith(FluxPrefix + i));
-
-                if (match is null) continue;
-
-                _match = match;
-                _fullBaseType = fullNameSpace;
-                _valid = true;
-                base.VisitClassDeclaration(node);
-                return;
-            }
-            base.VisitClassDeclaration(node);
-        }
-    }
-}
\ No newline at end of file
diff --git a/SourceGen/README.md b/SourceGen/README.md
deleted file mode 100644
index 83f774b..0000000
--- a/SourceGen/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-This code has been taken from [ProjectObsidian.SourceGenerators](https://github.com/Xlinka/Project-Obsidian/) which is distributed under the [GPL-3.0 licence](https://github.com/Xlinka/Project-Obsidian/blob/main/LICENSE) (as of writing), and thus
-any code in this directory and subdirectories is distributed as such as well.
-
-Yo! So I've made a change to this file. Basically, you can add `// no auto` to the **first** line of any protoflux file to prevent the generator from running.
-it IS case sensitive.
diff --git a/SourceGen/SourceGen.csproj b/SourceGen/SourceGen.csproj
deleted file mode 100644
index 3dfd3ee..0000000
--- a/SourceGen/SourceGen.csproj
+++ /dev/null
@@ -1,14 +0,0 @@
-﻿<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>netstandard2.0</TargetFramework>
-	  <LangVersion>latest</LangVersion>
-    <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
-		<NoWarn>MSB3277</NoWarn>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
-  </ItemGroup>
-
-</Project>


Reviews:
user: login: paradoxical-autumn
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-18T19:52:42Z
user: login: ErrorJan
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-18T20:03:24Z
user: login: paradoxical-autumn
body: as i said over discord, a cloudspawn doesnt fit ACA and is better suited for plugins that aren't as... dedicated.

sry just... imagine walking into a restaurant and finding out they sell.... uhh... thinking of a metaphor... furry art. youd be shocked and wonder "why is this here?"

so like its a cool node but dont waste ur code in a place it wont be found.

everything else looks good, i was just waiting to further understand the binding generator before approving changes.
state: CHANGES_REQUESTED
author_association: OWNER
submitted_at: 2025-03-18T20:08:37Z
user: login: paradoxical-autumn
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-18T20:10:39Z
user: login: paradoxical-autumn
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-18T20:11:20Z
user: login: paradoxical-autumn
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-18T20:17:35Z
user: login: paradoxical-autumn
body: yeh sure
state: APPROVED
author_association: OWNER
submitted_at: 2025-03-18T20:31:54Z

Review comments:
diff_hunk: @@ -173,11 +173,12 @@ private void GenSource( SourceProductionContext context, GeneratorSyntaxContext
                         break;
 
                     // ---- Calls ----
-                    case "Continuation":
-                        nodeOutputType = "INodeOperation";
-                        goto ContinueCalls;
                     case "Call":
                         nodeOutputType = "ISyncNodeOperation";
+                        goto ContinueCalls;
+                    case "Continuation":
path: ErrorsSourceGen/ErrorsSourceGen.cs
user: login: paradoxical-autumn
body: why is this case blank?
created_at: 2025-03-18T19:52:42Z
author_association: OWNER
diff_hunk: @@ -173,11 +173,12 @@ private void GenSource( SourceProductionContext context, GeneratorSyntaxContext
                         break;
 
                     // ---- Calls ----
-                    case "Continuation":
-                        nodeOutputType = "INodeOperation";
-                        goto ContinueCalls;
                     case "Call":
                         nodeOutputType = "ISyncNodeOperation";
+                        goto ContinueCalls;
+                    case "Continuation":
path: ErrorsSourceGen/ErrorsSourceGen.cs
user: login: ErrorJan
body: What do you mean blank?
created_at: 2025-03-18T20:03:24Z
author_association: COLLABORATOR
diff_hunk: @@ -173,11 +173,12 @@ private void GenSource( SourceProductionContext context, GeneratorSyntaxContext
                         break;
 
                     // ---- Calls ----
-                    case "Continuation":
-                        nodeOutputType = "INodeOperation";
-                        goto ContinueCalls;
                     case "Call":
                         nodeOutputType = "ISyncNodeOperation";
+                        goto ContinueCalls;
+                    case "Continuation":
path: ErrorsSourceGen/ErrorsSourceGen.cs
user: login: paradoxical-autumn
body: nvm, ive just never seen this syntax before
created_at: 2025-03-18T20:10:39Z
author_association: OWNER
path: ArbitraryComponentAccess/ProtoFlux/Other/CloudSpawn.cs
user: login: paradoxical-autumn
body: [REPOST FROM PR]
as i said over discord, a cloudspawn doesnt fit ACA and is better suited for plugins that aren't as... dedicated.

sry just... imagine walking into a restaurant and finding out they sell.... uhh... thinking of a metaphor... furry art. youd be shocked and wonder "why is this here?"

so like its a cool node but dont waste ur code in a place it wont be found.
created_at: 2025-03-18T20:11:20Z
author_association: OWNER
path: ArbitraryComponentAccess/ProtoFlux/Other/CloudSpawn.cs
user: login: paradoxical-autumn
body: resolved over discord
created_at: 2025-03-18T20:17:35Z
author_association: OWNER

PR comments:
user: login: paradoxical-autumn
created_at: 2025-03-18T16:37:25Z
body: what the f\*\*k
author_association: OWNER
user: login: ErrorJan
created_at: 2025-03-18T16:51:02Z
body: :3
author_association: COLLABORATOR
user: login: paradoxical-autumn
created_at: 2025-03-18T20:20:57Z
body: would this require renaming our plugin from ACA to `ACA and other shit` xD
/s
author_association: OWNER
user: login: paradoxical-autumn
created_at: 2025-03-18T20:33:50Z
body: TODO: rename plugin to `arbitrarily contained anarchy`
author_association: OWNER