Table of Contents

Class Compiler

Namespace
GrindFest
Assembly
GrindFest.dll
public class Compiler : Singleton<Compiler>
Inheritance
object
Compiler
Derived
Inherited Members

Fields

DefaultNamespaces
OnAssemblyCompiled
UseLocalTypes
_timestampCheckTimer
api
host
runtime

Properties

CachedScriptsDirectory
IsLocalHeroCompileInFlight

True while the party's bots are being (re)built. The compile is asynchronous in isolated mode, so anything that needs the bots - HeroController.StartBotting above all - has to be able to tell "they are being built right now" from "there are none and nothing is building them". That is a plain state question; it is deliberately not a guess based on the game mode or the platform.

OnlineScriptsDirectory

Scripts directory for AsyncOnline mode (validated bots only)

OverrideSupportsRuntimeCompilation

Test-only override of SupportsRuntimeCompilation.

ProjectFileExtension
ScriptFileExtension
ScriptsDirectory

Returns the appropriate scripts directory based on current GameMode. Solo mode uses Scripts, AsyncOnline mode uses ScriptsOnline.

SoloScriptsDirectory

Scripts directory for Solo mode (unrestricted experimentation)

SupportsIsolatedExecution
SupportsRuntimeCompilation

Whether this runtime can load and run code compiled at runtime.

The C# compiler is not the obstacle: Roslyn writes the PE image in managed code, and nothing here uses Reflection.Emit. What fails is the load - Assembly.Load(byte[]) has nowhere to go on an ahead-of-time runtime, because there is no JIT to turn the fresh IL into machine code. That is IL2CPP (WebGL, iOS, and an IL2CPP desktop player), where the same wall also stops AddComponent(type): the type only exists inside that assembly.

Probed rather than guessed from the platform name: creating a DynamicMethod and binding it to a delegate is exactly the capability in question, and it costs microseconds once.

SupportsTopLevelScripts

Methods

Compile(string, string, out byte[], string, bool, bool)

Compiles the bot scripts and hands the assembly back as data now. Only for callers that genuinely need the value synchronously (editor tooling, DevTests). It cannot run the isolated security analysis, which is asynchronous: waiting on that would freeze the caller and, on a runtime without threads, never finish at all. It also does not apply the player's isolated-API setting - it compiles what the caller asked for. Everything the game runs goes through CompileAsync(string, string, string, bool, bool), which does both.

CompileAndPrepareLocalHeroesAsync()

Starts the local-hero compile, or joins the one already running, and hands back the task to await. Never blocks, so it is safe to call from anywhere, including a UI callback.

CompileAsync(string, string, string, bool, bool)

The asynchronous door to the same compilation: the isolated security analysis is awaited instead of blocked on, and the player's isolated-API setting is honoured. This is the path the game itself uses.

CreateCompilation(string, List<SyntaxTree>, List<MetadataReference>, bool)
CreateCompilationOptions(bool)
CreateParseOptions(SourceCodeKind)
EnsureIsolatedRuntime()
EnsureScriptFileExists(string)
GetAdditionalDllReferences(string)
GetDefaultScript(string)
GetOnlineDefaultScript(string)

Default script template for AsyncOnline mode - requires AutomaticHero class for validation

GetReferencesFromProj(string)
GetScriptFile(string)
GetSoloDefaultScript(string)

Default script template for Solo mode - uses Hero.* static methods (simpler for beginners)

IsScriptFile(string, string, out SyntaxTree)
Parse(string, string, ParseOptions)
RequestLocalHeroCompile()

Asks for the party's scripts to be recompiled and returns immediately - the compile finishes on its own. This is the entry point for everything that does not need the bots as data: adding a hero, switching botting on, and the script-change watcher in GrindFest.Compiler.Update(). Whoever does need them awaits CompileAndPrepareLocalHeroesAsync() instead.

UpdateProjImplicitUsings(string, bool)