Decompiled source of LuaEngine v0.4.0

LuaEngine.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using DG.Tweening;
using HarmonyLib;
using LuaEngine.Alarms;
using LuaEngine.Modules;
using LuaEngine.Mono;
using MapStation.Common;
using MapStation.Plugin;
using Microsoft.CodeAnalysis;
using MoonSharp.Interpreter;
using Reptile;
using TMPro;
using UnityEngine;
using UnityEngine.Playables;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("LuaEngine")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("LuaEngine Plugin for BRC.")]
[assembly: AssemblyFileVersion("0.4.0.0")]
[assembly: AssemblyInformationalVersion("0.4.0+ecb3c4555884938466d8d4a15fc91f2b48fc9b0f")]
[assembly: AssemblyProduct("LuaEngine")]
[assembly: AssemblyTitle("LuaEngine")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LuaEngine
{
	public interface ILuaModule
	{
		void OnRegister(Script script);
	}
	public interface ILuaReloadable
	{
		void OnReload();
	}
	[MoonSharpUserData]
	public class LuaAnimator : LuaBuiltInBehaviour
	{
		public Animator Animator;

		[MoonSharpHidden]
		public LuaAnimator(Animator animator, Script script)
			: base((Behaviour)(object)animator, script)
		{
			Animator = animator;
		}

		internal static LuaAnimator CastMethod(Animator animator)
		{
			return new LuaAnimator(animator, LuaManager.Instance.GlobalScript);
		}

		public void SetTrigger(string name)
		{
			Animator.SetTrigger(name);
		}

		public void SetBool(string name, bool value)
		{
			Animator.SetBool(name, value);
		}

		public bool GetBool(string name)
		{
			return Animator.GetBool(name);
		}

		public void SetInteger(string name, int value)
		{
			Animator.SetInteger(name, value);
		}

		public int GetInteger(string name)
		{
			return Animator.GetInteger(name);
		}

		public void SetFloat(string name, float value)
		{
			Animator.SetFloat(name, value);
		}

		public float GetFloat(string name)
		{
			return Animator.GetFloat(name);
		}
	}
	[MoonSharpUserData]
	public class LuaAudioSource : LuaBuiltInBehaviour
	{
		public AudioSource AudioSource;

		[MoonSharpHidden]
		public LuaAudioSource(AudioSource audio, Script script)
			: base((Behaviour)(object)audio, script)
		{
			AudioSource = audio;
		}

		internal static LuaAudioSource CastMethod(AudioSource audioSource)
		{
			return new LuaAudioSource(audioSource, LuaManager.Instance.GlobalScript);
		}

		public void Play()
		{
			AudioSource.Play();
		}

		public void Stop()
		{
			AudioSource.Stop();
		}

		public void Pause()
		{
			AudioSource.Pause();
		}

		public void SetMixerGroup(int mixerGroup)
		{
			AudioSource.outputAudioMixerGroup = Core.Instance.AudioManager.mixerGroups[mixerGroup];
		}
	}
	[MoonSharpUserData]
	public class LuaBuiltInBehaviour : LuaBuiltInComponent
	{
		public Behaviour Behaviour;

		public bool IsActiveAndEnabled => Behaviour.isActiveAndEnabled;

		public bool Enabled
		{
			get
			{
				return Behaviour.enabled;
			}
			set
			{
				Behaviour.enabled = true;
			}
		}

		[MoonSharpHidden]
		public LuaBuiltInBehaviour(Behaviour behaviour, Script script)
			: base((Component)(object)behaviour, script)
		{
			Behaviour = behaviour;
		}
	}
	[MoonSharpUserData]
	public class LuaBuiltInComponent
	{
		public LuaGameObject GameObject;

		public Component Component;

		[MoonSharpHidden]
		public LuaBuiltInComponent(Component component, Script script)
		{
			Component = component;
			GameObject = new LuaGameObject(component.gameObject);
		}
	}
	public class LuaCast
	{
		public Type CSharpType { get; private set; }

		public Type LuaType { get; private set; }

		public Delegate CastMethod { get; private set; }

		public static LuaCast Create<TLua, TCSharp>(Func<TCSharp, TLua> castMethod) where TLua : class where TCSharp : class
		{
			return new LuaCast
			{
				CastMethod = castMethod,
				LuaType = castMethod.Method.ReturnType,
				CSharpType = castMethod.Method.GetParameters()[0].ParameterType
			};
		}
	}
	public static class LuaCastFactory
	{
		private static Dictionary<Type, LuaCast> CastFromCSharpType = new Dictionary<Type, LuaCast>();

		private static Dictionary<string, LuaCast> CastFromLuaTypeName = new Dictionary<string, LuaCast>();

		internal static void Initialize()
		{
			RegisterCasts(LuaCast.Create<LuaPlayer, Player>(LuaPlayer.CastMethod), LuaCast.Create<LuaScriptBehavior, ScriptBehavior>(LuaScriptBehavior.CastMethod), LuaCast.Create<LuaAnimator, Animator>(LuaAnimator.CastMethod), LuaCast.Create<LuaAudioSource, AudioSource>(LuaAudioSource.CastMethod), LuaCast.Create<LuaScriptStringValue, ScriptStringValue>(LuaScriptStringValue.CastMethod), LuaCast.Create<LuaScriptNumberValue, ScriptNumberValue>(LuaScriptNumberValue.CastMethod), LuaCast.Create<LuaScriptGameObjectValue, ScriptGameObjectValue>(LuaScriptGameObjectValue.CastMethod), LuaCast.Create<LuaScriptComponentValue, ScriptComponentValue>(LuaScriptComponentValue.CastMethod), LuaCast.Create<LuaPlayableDirector, PlayableDirector>(LuaPlayableDirector.CastMethod));
		}

		public static Type GetCSharpTypeFromLuaTypeName(string luaTypeName)
		{
			if (CastFromLuaTypeName.TryGetValue(luaTypeName, out var value))
			{
				return value.CSharpType;
			}
			return null;
		}

		public static T CastCSharpTypeToLuaType<T>(object CSharpObject) where T : class
		{
			if (CastFromCSharpType.TryGetValue(CSharpObject.GetType(), out var value))
			{
				return value.CastMethod.DynamicInvoke(CSharpObject) as T;
			}
			return null;
		}

		public static void RegisterCasts(params LuaCast[] casts)
		{
			foreach (LuaCast luaCast in casts)
			{
				CastFromCSharpType[luaCast.CSharpType] = luaCast;
				CastFromLuaTypeName[luaCast.LuaType.Name] = luaCast;
			}
		}
	}
	public static class LuaDatabase
	{
		public static List<LuaScript> AutoRunScripts;

		public static Dictionary<string, LuaScript> BehaviorScripts;

		private static ManualLogSource LogSource;

		private static bool CheckedMapStationInstalled;

		private static bool CachedMapStationInstalled;

		private static string PluginPath;

		private static bool MapStationInstalled
		{
			get
			{
				if (CheckedMapStationInstalled)
				{
					return CachedMapStationInstalled;
				}
				CachedMapStationInstalled = CheckMapStationInstalled();
				CheckedMapStationInstalled = true;
				return CachedMapStationInstalled;
			}
		}

		private static bool CheckMapStationInstalled()
		{
			return Chainloader.PluginInfos.ContainsKey("MapStation.Plugin");
		}

		internal static void Initialize(string pluginPath)
		{
			PluginPath = pluginPath;
			LogSource = Logger.CreateLogSource("Lua Database");
			InitializeScripts();
		}

		public static void Reload()
		{
			InitializeScripts();
		}

		private static void InitializeScripts()
		{
			AutoRunScripts = new List<LuaScript>();
			BehaviorScripts = new Dictionary<string, LuaScript>();
			LoadPluginScripts();
			if (MapStationInstalled)
			{
				LoadMapScripts();
			}
		}

		private static void LoadPluginScripts()
		{
			string[] files = Directory.GetFiles(PluginPath, "*.luamod", SearchOption.AllDirectories);
			foreach (string text in files)
			{
				LogSource.LogInfo((object)("Loading Lua scripts in " + text));
				LoadPluginZip(text);
			}
		}

		private static void LoadMapScripts()
		{
			foreach (KeyValuePair<Stage, PluginMapDatabaseEntry> map in MapDatabase.Instance.maps)
			{
				ZipArchiveEntry entry = ZipFile.OpenRead(map.Value.zipPath).GetEntry("lua.luamod");
				if (entry != null)
				{
					Stream stream = entry.Open();
					ZipArchive zipArchive = new ZipArchive(stream);
					LoadPluginZip(zipArchive);
					zipArchive.Dispose();
					stream.Dispose();
				}
			}
		}

		public static void LoadPluginZip(ZipArchive archive)
		{
			foreach (ZipArchiveEntry entry in archive.Entries)
			{
				string text = entry.FullName.Replace("\\", "/");
				string text2 = entry.Name.Replace("\\", "/");
				if (!text2.EndsWith(".lua"))
				{
					continue;
				}
				string body = ReadStringZipEntry(entry);
				if (text.StartsWith("autorun/"))
				{
					LuaScript luaScript = LuaScript.FromString(text2, body, usePriority: true);
					if (luaScript != null)
					{
						AutoRunScripts.Add(luaScript);
					}
				}
				else if (text.StartsWith("behavior/"))
				{
					LuaScript luaScript2 = LuaScript.FromString(text2, body, usePriority: true);
					if (luaScript2 != null)
					{
						BehaviorScripts[luaScript2.Name] = luaScript2;
					}
				}
			}
		}

		public static void LoadPluginZip(string zipPath)
		{
			ZipArchive zipArchive = ZipFile.OpenRead(zipPath);
			LoadPluginZip(zipArchive);
			zipArchive.Dispose();
		}

		private static string ReadStringZipEntry(ZipArchiveEntry entry)
		{
			using Stream stream = entry.Open();
			using StreamReader streamReader = new StreamReader(stream);
			return streamReader.ReadToEnd();
		}
	}
	[MoonSharpUserData]
	public class LuaEventHandler : ILuaReloadable
	{
		private Dictionary<string, DynValue> _callbackByGUID = new Dictionary<string, DynValue>();

		private Script _script;

		[MoonSharpHidden]
		public LuaEventHandler(Script script)
		{
			_script = script;
			LuaReloadableManager.Register(this);
		}

		[MoonSharpHidden]
		public void OnReload()
		{
			Clear();
		}

		public void Clear()
		{
			_callbackByGUID = new Dictionary<string, DynValue>();
		}

		public string Add(DynValue callback)
		{
			string text = Guid.NewGuid().ToString();
			_callbackByGUID[text] = callback;
			return text;
		}

		public void Remove(string callbackGUID)
		{
			if (callbackGUID != null && _callbackByGUID.TryGetValue(callbackGUID, out var _))
			{
				_callbackByGUID.Remove(callbackGUID);
			}
		}

		public void Invoke(params object[] args)
		{
			foreach (KeyValuePair<string, DynValue> item in _callbackByGUID)
			{
				if (item.Value != null && !item.Value.IsNilOrNan())
				{
					LuaManager.Instance.Call(item.Value, args);
				}
			}
		}
	}
	[MoonSharpUserData]
	public class LuaGameObject
	{
		[MoonSharpHidden]
		public GameObject Handle;

		public LuaGameObject Parent
		{
			get
			{
				return new LuaGameObject(((Component)Handle.transform.parent).gameObject);
			}
			set
			{
				Handle.transform.SetParent(value.Handle.transform, true);
			}
		}

		public Table Velocity
		{
			get
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				Rigidbody component = Handle.gameObject.GetComponent<Rigidbody>();
				if ((Object)(object)component == (Object)null)
				{
					return LuaMathUtils.Vector3ToTable(Vector3.zero);
				}
				return LuaMathUtils.Vector3ToTable(component.velocity);
			}
			set
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				Rigidbody component = Handle.gameObject.GetComponent<Rigidbody>();
				if (!((Object)(object)component == (Object)null))
				{
					component.velocity = LuaMathUtils.TableToVector3(value);
				}
			}
		}

		public bool ActiveInHierarchy => Handle.gameObject.activeInHierarchy;

		public bool Active
		{
			get
			{
				return Handle.gameObject.activeSelf;
			}
			set
			{
				Handle.gameObject.SetActive(value);
			}
		}

		public int InstanceID => ((Object)Handle.gameObject).GetInstanceID();

		public string Name
		{
			get
			{
				return ((Object)Handle.gameObject).name;
			}
			set
			{
				((Object)Handle.gameObject).name = value;
			}
		}

		[MoonSharpHidden]
		public LuaGameObject(GameObject handle)
		{
			Handle = handle;
		}

		public LuaGameObject Find(string name)
		{
			Transform val = Handle.gameObject.transform.Find(name);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			return new LuaGameObject(((Component)val).gameObject);
		}

		public LuaGameObject FindRecursive(string name)
		{
			Transform val = TransformExtentions.FindRecursive(Handle.gameObject.transform, name);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			return new LuaGameObject(((Component)val).gameObject);
		}

		public Table GetLocalPosition()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return LuaMathUtils.Vector3ToTable(Handle.transform.localPosition);
		}

		public void SetLocalPosition(Table position)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			Handle.transform.localPosition = LuaMathUtils.TableToVector3(position);
		}

		public Table GetPosition()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return LuaMathUtils.Vector3ToTable(Handle.transform.position);
		}

		public void SetPosition(Table position)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			Handle.transform.position = LuaMathUtils.TableToVector3(position);
		}

		public void AddPosition(Table offset)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = Handle.transform;
			transform.position += LuaMathUtils.TableToVector3(offset);
		}

		public Table GetLocalEulerAngles()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return LuaMathUtils.Vector3ToTable(Handle.transform.localEulerAngles);
		}

		public void SetLocalEulerAngles(Table eulerAngles)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			Handle.transform.localRotation = Quaternion.Euler(LuaMathUtils.TableToVector3(eulerAngles));
		}

		public Table GetEulerAngles()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return LuaMathUtils.Vector3ToTable(Handle.transform.eulerAngles);
		}

		public void SetEulerAngles(Table eulerAngles)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			Handle.transform.rotation = Quaternion.Euler(LuaMathUtils.TableToVector3(eulerAngles));
		}

		public void Rotate(Table axis, float angle)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			Handle.transform.Rotate(LuaMathUtils.TableToVector3(axis), angle);
		}

		public Table GetForward()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return LuaMathUtils.Vector3ToTable(Handle.transform.forward);
		}

		public Table GetRight()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return LuaMathUtils.Vector3ToTable(Handle.transform.right);
		}

		public Table GetUp()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return LuaMathUtils.Vector3ToTable(Handle.transform.up);
		}

		public LuaGameObject Instantiate()
		{
			GameObject obj = Object.Instantiate<GameObject>(Handle.gameObject);
			LuaUtility.OnInstantiate(obj);
			return new LuaGameObject(obj);
		}

		public void Destroy()
		{
			Object.Destroy((Object)(object)Handle.gameObject);
		}

		public LuaScriptBehavior AddScriptBehavior(string scriptFilename)
		{
			ScriptBehavior scriptBehavior = Handle.gameObject.AddComponent<ScriptBehavior>();
			scriptBehavior.LuaScriptName = scriptFilename;
			scriptBehavior.Initialize();
			return new LuaScriptBehavior(scriptBehavior, LuaManager.Instance.GlobalScript);
		}

		public LuaBuiltInComponent GetLuaComponent(string luaComponentName)
		{
			Type cSharpTypeFromLuaTypeName = LuaCastFactory.GetCSharpTypeFromLuaTypeName(luaComponentName);
			if (cSharpTypeFromLuaTypeName == null)
			{
				return null;
			}
			Component component = Handle.gameObject.GetComponent(cSharpTypeFromLuaTypeName);
			if ((Object)(object)component == (Object)null)
			{
				return null;
			}
			return LuaCastFactory.CastCSharpTypeToLuaType<LuaBuiltInComponent>(component);
		}

		public LuaScriptBehavior GetScriptBehavior(string scriptFilename)
		{
			ScriptBehavior[] components = Handle.GetComponents<ScriptBehavior>();
			foreach (ScriptBehavior scriptBehavior in components)
			{
				if (scriptBehavior.LuaScriptName == scriptFilename)
				{
					return new LuaScriptBehavior(scriptBehavior, LuaManager.Instance.GlobalScript);
				}
			}
			return null;
		}

		public static LuaGameObject New(string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			return new LuaGameObject(new GameObject(name));
		}

		public LuaScriptStringValue GetStringValue(string name)
		{
			return new LuaScriptStringValue((from comp in Handle.GetComponents<ScriptStringValue>()
				where comp.Name == name
				select comp).FirstOrDefault(), LuaManager.Instance.GlobalScript);
		}

		public LuaScriptNumberValue GetNumberValue(string name)
		{
			return new LuaScriptNumberValue((from comp in Handle.GetComponents<ScriptNumberValue>()
				where comp.Name == name
				select comp).FirstOrDefault(), LuaManager.Instance.GlobalScript);
		}

		public LuaScriptGameObjectValue GetGameObjectValue(string name)
		{
			return new LuaScriptGameObjectValue((from comp in Handle.GetComponents<ScriptGameObjectValue>()
				where comp.Name == name
				select comp).FirstOrDefault(), LuaManager.Instance.GlobalScript);
		}

		public LuaScriptComponentValue GetComponentValue(string name)
		{
			return new LuaScriptComponentValue((from comp in Handle.GetComponents<ScriptComponentValue>()
				where comp.Name == name
				select comp).FirstOrDefault(), LuaManager.Instance.GlobalScript);
		}

		public void SetStringValue(string name, string value)
		{
			ScriptStringValue scriptStringValue = GetStringValue(name).ScriptStringValue;
			if ((Object)(object)scriptStringValue == (Object)null)
			{
				scriptStringValue = Handle.AddComponent<ScriptStringValue>();
			}
			scriptStringValue.Value = value;
		}

		public void SetNumberValue(string name, double value)
		{
			ScriptNumberValue scriptNumberValue = GetNumberValue(name).ScriptNumberValue;
			if ((Object)(object)scriptNumberValue == (Object)null)
			{
				scriptNumberValue = Handle.AddComponent<ScriptNumberValue>();
			}
			scriptNumberValue.Value = value;
		}

		public void SetGameObjectValue(string name, LuaGameObject value)
		{
			ScriptGameObjectValue scriptGameObjectValue = GetGameObjectValue(name).ScriptGameObjectValue;
			if ((Object)(object)scriptGameObjectValue == (Object)null)
			{
				scriptGameObjectValue = Handle.AddComponent<ScriptGameObjectValue>();
			}
			scriptGameObjectValue.Value = value.Handle;
		}

		public void SetComponentValue(string name, LuaBuiltInComponent value)
		{
			ScriptComponentValue scriptComponentValue = GetComponentValue(name).ScriptComponentValue;
			if ((Object)(object)scriptComponentValue == (Object)null)
			{
				scriptComponentValue = Handle.AddComponent<ScriptComponentValue>();
			}
			scriptComponentValue.Value = value.Component;
		}
	}
	public class LuaManager : MonoBehaviour
	{
		public Script GlobalScript;

		private ManualLogSource _logSource;

		private ManualLogSource _scriptLogSource;

		public static LuaManager Instance { get; private set; }

		internal static void Create()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			GameObject val = new GameObject("Lua Manager");
			LuaManager instance = val.AddComponent<LuaManager>();
			Object.DontDestroyOnLoad((Object)val);
			Instance = instance;
		}

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			_logSource = Logger.CreateLogSource("Lua Manager");
			_scriptLogSource = Logger.CreateLogSource("Global Lua");
			GlobalScript = new Script();
			GlobalScript.Options.DebugPrint = delegate(string message)
			{
				_scriptLogSource.LogInfo((object)message);
			};
			RegisterModules();
			RunScripts();
		}

		private void RunScripts()
		{
			LuaDatabase.AutoRunScripts = LuaDatabase.AutoRunScripts.OrderBy((LuaScript script) => script.Priority).ToList();
			foreach (LuaScript autoRunScript in LuaDatabase.AutoRunScripts)
			{
				_logSource.LogInfo((object)$"Running Autorun Script {autoRunScript.Name} with priority {autoRunScript.Priority}");
				autoRunScript.Run(GlobalScript);
			}
		}

		public DynValue Call(DynValue function, params object[] args)
		{
			//IL_0011: Expected O, but got Unknown
			try
			{
				return GlobalScript.Call(function, args);
			}
			catch (InterpreterException val)
			{
				InterpreterException val2 = val;
				Debug.LogError((object)("Error executing lua function!" + Environment.NewLine + val2.DecoratedMessage));
			}
			return null;
		}

		public void Reload()
		{
			LuaReloadableManager.OnReload();
			LuaDatabase.Reload();
			RunScripts();
		}

		private void RegisterModules()
		{
			UserData.RegisterType<LuaAnimator>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaAudioSource>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaBuiltInBehaviour>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaBuiltInComponent>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaEventHandler>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaGameObject>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaPlayableDirector>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaPlayer>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaScriptBehavior>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaScriptComponentValue>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaScriptGameObjectValue>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaScriptNumberValue>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaScriptStringValue>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaScriptValue>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaAlarmManager>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaCore>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaSequenceHandler>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaStageManager>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaUI>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaUnityEngine>((InteropAccessMode)7, (string)null);
			UserData.RegisterType<LuaWorldHandler>((InteropAccessMode)7, (string)null);
			_logSource.LogInfo((object)"Registering Lua modules");
			LuaStageManager module = new LuaStageManager();
			RegisterModule(module);
			LuaCore module2 = new LuaCore();
			RegisterModule(module2);
			LuaUnityEngine module3 = new LuaUnityEngine();
			RegisterModule(module3);
			LuaWorldHandler module4 = new LuaWorldHandler();
			RegisterModule(module4);
			LuaUI module5 = new LuaUI();
			RegisterModule(module5);
			LuaAlarmManager module6 = new LuaAlarmManager();
			RegisterModule(module6);
			LuaSequenceHandler module7 = new LuaSequenceHandler();
			RegisterModule(module7);
		}

		private void RegisterModule(ILuaModule module)
		{
			module.OnRegister(GlobalScript);
		}
	}
	public static class LuaMathUtils
	{
		public static Vector3 TableToVector3(Table table)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3((float)table.Get("x").CastToNumber().Value, (float)table.Get("y").CastToNumber().Value, (float)table.Get("z").CastToNumber().Value);
		}

		public static Table Vector3ToTable(Vector3 vector)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			Script globalScript = LuaManager.Instance.GlobalScript;
			object obj = globalScript.Globals[(object)"Vector3"];
			Table val = (Table)((obj is Table) ? obj : null);
			return globalScript.Call(val.Get("New"), new object[3] { vector.x, vector.y, vector.z }).Table;
		}
	}
	[MoonSharpUserData]
	public class LuaPlayableDirector : LuaBuiltInBehaviour
	{
		public PlayableDirector PlayableDirector;

		public double Time => PlayableDirector.time;

		public double Duration => PlayableDirector.duration;

		[MoonSharpHidden]
		public LuaPlayableDirector(PlayableDirector playableDirector, Script script)
			: base((Behaviour)(object)playableDirector, script)
		{
			PlayableDirector = playableDirector;
		}

		internal static LuaPlayableDirector CastMethod(PlayableDirector playableDirector)
		{
			return new LuaPlayableDirector(playableDirector, LuaManager.Instance.GlobalScript);
		}

		public void SkipTo(double time, bool keepGameplayCamera = true)
		{
			PlayableDirector.time = time;
			PlayableDirector.Evaluate();
			if (keepGameplayCamera && (Object)(object)WorldHandler.instance.CurrentCamera != (Object)(object)WorldHandler.instance.GetCurrentPlayer().cam.cam)
			{
				((Component)WorldHandler.instance.CurrentCamera).gameObject.SetActive(false);
			}
		}

		public void Play()
		{
			PlayableDirector.Play();
		}

		public void Pause()
		{
			PlayableDirector.Pause();
		}

		public void Stop()
		{
			PlayableDirector.Stop();
		}
	}
	[MoonSharpUserData]
	public class LuaPlayer : LuaBuiltInBehaviour
	{
		public Player Player;

		public bool AllowClimb
		{
			get
			{
				return PlayerLuaEngineComponent.Get(Player).AllowClimb;
			}
			set
			{
				PlayerLuaEngineComponent.Get(Player).AllowClimb = value;
			}
		}

		public bool UserInputEnabled
		{
			get
			{
				return Player.userInputEnabled;
			}
			set
			{
				Player.userInputEnabled = value;
			}
		}

		public LuaEventHandler OnLandCombo => PlayerLuaEngineComponent.Get(Player)?.OnLandCombo;

		public LuaEventHandler OnDropCombo => PlayerLuaEngineComponent.Get(Player)?.OnDropCombo;

		public bool IsComboing => Player.IsComboing();

		public float ScoreMultiplier
		{
			get
			{
				return Player.scoreMultiplier;
			}
			set
			{
				Player.scoreMultiplier = value;
			}
		}

		public float BaseScore
		{
			get
			{
				return Player.baseScore;
			}
			set
			{
				Player.baseScore = value;
			}
		}

		public bool Grounded => Player.IsGrounded();

		public int MoveStyleEquipped => (int)Player.moveStyleEquipped;

		public int MoveStyle => (int)Player.moveStyle;

		public float NormalizedHP => Player.GetNormalizedHP();

		public float MaxHP
		{
			get
			{
				return Player.maxHP;
			}
			set
			{
				Player.maxHP = value;
			}
		}

		public float HP
		{
			get
			{
				return Player.HP;
			}
			set
			{
				Player.HP = value;
			}
		}

		public string AbilityName
		{
			get
			{
				if (Player.ability == null)
				{
					return null;
				}
				return ((object)Player.ability).GetType().Name;
			}
		}

		public bool IsTooBusyForSuddenCutscenes => Player.IsTooBusyForSuddenCutscenes();

		public bool IsBusyWithSequence => Player.IsBusyWithSequence();

		public bool IsDead => Player.IsDead();

		public bool IsAI
		{
			get
			{
				return Player.isAI;
			}
			set
			{
				Player.isAI = value;
			}
		}

		public float BoostCharge
		{
			get
			{
				return Player.boostCharge;
			}
			set
			{
				Player.boostCharge = value;
			}
		}

		public float MaxBoostCharge
		{
			get
			{
				return Player.maxBoostCharge;
			}
			set
			{
				Player.maxBoostCharge = value;
			}
		}

		public Table Velocity
		{
			get
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				return LuaMathUtils.Vector3ToTable(Player.motor.velocity);
			}
			set
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				Player.motor.velocity = LuaMathUtils.TableToVector3(value);
			}
		}

		[MoonSharpHidden]
		public LuaPlayer(Player player, Script script)
			: base((Behaviour)(object)player, script)
		{
			Player = player;
		}

		internal static LuaPlayer CastMethod(Player player)
		{
			return new LuaPlayer(player, LuaManager.Instance.GlobalScript);
		}

		public void ForceUnground(bool resetVisual)
		{
			Player.ForceUnground(resetVisual);
		}

		public void AddBoostCharge(float amount)
		{
			Player.AddBoostCharge(amount);
		}

		public void SetRotation(Table forward)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			Player.SetRotation(LuaMathUtils.TableToVector3(forward));
		}

		public void SetRotationHard(Table forward)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			Player.SetRotHard(LuaMathUtils.TableToVector3(forward));
		}

		public void GetHit(int damage, Table damageDirection, string knockbackType)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			KnockbackType val = (KnockbackType)5;
			switch (knockbackType)
			{
			case "Stationary":
				val = (KnockbackType)0;
				break;
			case "Far":
				val = (KnockbackType)1;
				break;
			case "Big":
				val = (KnockbackType)2;
				break;
			case "ShieldBash":
				val = (KnockbackType)3;
				break;
			case "Fall":
				val = (KnockbackType)4;
				break;
			case "None":
				val = (KnockbackType)5;
				break;
			}
			Player.GetHit(damage, LuaMathUtils.TableToVector3(damageDirection), val);
		}

		public void ChangeHP(int damage)
		{
			Player.ChangeHP(damage);
		}

		public void SetCurrentMoveStyleEquipped(int moveStyle)
		{
			Player.SetCurrentMoveStyleEquipped((MoveStyle)moveStyle, true, true);
		}

		public void SwitchToEquippedMovestyle(bool set, bool doAirTrick, bool showEffect)
		{
			Player.SwitchToEquippedMovestyle(set, doAirTrick, true, showEffect);
		}

		public void LandCombo()
		{
			Player.LandCombo();
		}

		public void DropCombo()
		{
			Player.DropCombo();
		}

		public void AddScoreMultiplier()
		{
			Player.AddScoreMultiplier();
		}

		public void DoTrick(string trickName, int score)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			Player.currentTrickPoints = score;
			Player.currentTrickType = (TrickType)13;
			Player.currentTrickName = trickName;
			Player.currentTrickOnFoot = !Player.usingEquippedMovestyle;
			Player player = Player;
			player.baseScore += (float)(int)((float)Player.currentTrickPoints * Player.scoreFactor);
			if (Player.scoreMultiplier == 0f)
			{
				Player.scoreMultiplier = 1f;
			}
			if (Player.tricksInCombo == 0 && (Object)(object)Player.ui != (Object)null)
			{
				Player.ui.SetTrickingChargeBarActive(true);
			}
			Player player2 = Player;
			player2.tricksInCombo++;
			if (Player.tricksInCombo >= 5)
			{
				float num = Player.gainBoostChargeCurve.Evaluate(Mathf.Min((float)Player.tricksInCombo, 50f) / 50f);
				Player.showAddCharge = num;
				Player.AddBoostCharge(num);
			}
			Player.moveInScoreTimer = 1f;
		}

		public void PlayVoice(int audioClipID, int voicePriority, bool fromPlayer = true)
		{
			Player.PlayVoice((AudioClipID)audioClipID, (VoicePriority)voicePriority, fromPlayer);
		}

		public void RegainAirMobility()
		{
			Player.RegainAirMobility();
		}
	}
	public static class LuaReloadableManager
	{
		private static List<WeakReference> Reloadables = new List<WeakReference>();

		public static void Register(ILuaReloadable reloadable)
		{
			Purge();
			Reloadables.Add(new WeakReference(reloadable));
		}

		internal static void Purge()
		{
			Reloadables = Reloadables.Where((WeakReference reloadable) => reloadable.IsAlive).ToList();
		}

		internal static void OnReload()
		{
			Purge();
			foreach (WeakReference reloadable in Reloadables)
			{
				((ILuaReloadable)reloadable.Target).OnReload();
			}
		}
	}
	public class LuaScript
	{
		private const string InternalVariablePrefix = "_LUAENGINE_INTERNAL_";

		private const string PriorityPrefix = "--PRIORITY:";

		public string Name = "";

		public string Body = "";

		public int Priority;

		public static LuaScript FromString(string name, string body, bool usePriority = false)
		{
			LuaScript luaScript = new LuaScript();
			luaScript.Body = body;
			luaScript.Name = name;
			if (usePriority)
			{
				using StringReader stringReader = new StringReader(luaScript.Body);
				string text;
				while ((text = stringReader.ReadLine()) != null)
				{
					if (text.StartsWith("--PRIORITY:") && int.TryParse(text.Substring("--PRIORITY:".Length), out var result))
					{
						luaScript.Priority = result;
						break;
					}
				}
			}
			return luaScript;
		}

		private DynValue DoString(Script script, string body, string name)
		{
			//IL_000d: Expected O, but got Unknown
			try
			{
				return script.DoString(body, (Table)null, name);
			}
			catch (InterpreterException val)
			{
				InterpreterException val2 = val;
				Debug.LogError((object)("Error executing lua script " + name + "!" + Environment.NewLine + val2.DecoratedMessage));
			}
			return null;
		}

		public void Run(Script script)
		{
			DoString(script, Body, Name);
		}

		public void RunForScriptBehavior(Script script, LuaScriptBehavior scriptBehavior)
		{
			string body = AddLocalContext(script, Body, "script", scriptBehavior);
			DoString(script, body, Name);
			RemoveLocalContext(script, "script");
		}

		private string AddLocalContext(Script script, string body, string variableName, object variableValue)
		{
			script.Globals[(object)("_LUAENGINE_INTERNAL_" + variableName)] = variableValue;
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("local " + variableName + " = _LUAENGINE_INTERNAL_" + variableName);
			stringBuilder.AppendLine("_LUAENGINE_INTERNAL_" + variableName + " = nil");
			stringBuilder.AppendLine(body);
			return stringBuilder.ToString();
		}

		private void RemoveLocalContext(Script script, string variableName)
		{
			script.Globals[(object)("_LUAENGINE_INTERNAL_" + variableName)] = DynValue.Nil;
		}
	}
	[MoonSharpUserData]
	public class LuaScriptBehavior : LuaBuiltInBehaviour
	{
		public ScriptBehavior ScriptBehavior;

		public string ScriptName => ScriptBehavior.LuaScriptName;

		public LuaEventHandler OnStart => ScriptBehavior.OnStart;

		public LuaEventHandler OnDestroy => ScriptBehavior.OnDestroyed;

		public LuaEventHandler OnCollisionEnter => ScriptBehavior.OnAnyCollisionEnter;

		public LuaEventHandler OnCollisionStay => ScriptBehavior.OnAnyCollisionStay;

		public LuaEventHandler OnCollisionExit => ScriptBehavior.OnAnyCollisionExit;

		public LuaEventHandler OnPlayerCollisionEnter => ScriptBehavior.OnPlayerCollisionEnter;

		public LuaEventHandler OnPlayerCollisionStay => ScriptBehavior.OnPlayerCollisionStay;

		public LuaEventHandler OnPlayerCollisionExit => ScriptBehavior.OnPlayerCollisionExit;

		public LuaEventHandler OnTriggerEnter => ScriptBehavior.OnAnyTriggerEnter;

		public LuaEventHandler OnTriggerStay => ScriptBehavior.OnAnyTriggerStay;

		public LuaEventHandler OnTriggerExit => ScriptBehavior.OnAnyTriggerExit;

		public LuaEventHandler OnPlayerTriggerEnter => ScriptBehavior.OnPlayerTriggerEnter;

		public LuaEventHandler OnPlayerTriggerStay => ScriptBehavior.OnPlayerTriggerStay;

		public LuaEventHandler OnPlayerTriggerExit => ScriptBehavior.OnPlayerTriggerExit;

		[MoonSharpHidden]
		public LuaScriptBehavior(ScriptBehavior scriptBehavior, Script script)
			: base((Behaviour)(object)scriptBehavior, script)
		{
			ScriptBehavior = scriptBehavior;
		}

		internal static LuaScriptBehavior CastMethod(ScriptBehavior scriptBehavior)
		{
			return new LuaScriptBehavior(scriptBehavior, LuaManager.Instance.GlobalScript);
		}
	}
	[MoonSharpUserData]
	public class LuaScriptComponentValue : LuaScriptValue
	{
		public ScriptComponentValue ScriptComponentValue;

		public LuaBuiltInComponent Value
		{
			get
			{
				return LuaCastFactory.CastCSharpTypeToLuaType<LuaBuiltInComponent>(ScriptComponentValue.Value);
			}
			set
			{
				ScriptComponentValue.Value = value.Component;
			}
		}

		[MoonSharpHidden]
		public LuaScriptComponentValue(ScriptComponentValue value, Script script)
			: base(value, script)
		{
			ScriptComponentValue = value;
		}

		internal static LuaScriptComponentValue CastMethod(ScriptComponentValue componentValue)
		{
			return new LuaScriptComponentValue(componentValue, LuaManager.Instance.GlobalScript);
		}
	}
	[MoonSharpUserData]
	public class LuaScriptGameObjectValue : LuaScriptValue
	{
		public ScriptGameObjectValue ScriptGameObjectValue;

		public LuaGameObject Value
		{
			get
			{
				return new LuaGameObject(ScriptGameObjectValue.Value);
			}
			set
			{
				ScriptGameObjectValue.Value = value.Handle;
			}
		}

		[MoonSharpHidden]
		public LuaScriptGameObjectValue(ScriptGameObjectValue value, Script script)
			: base(value, script)
		{
			ScriptGameObjectValue = value;
		}

		internal static LuaScriptGameObjectValue CastMethod(ScriptGameObjectValue gameObjectValue)
		{
			return new LuaScriptGameObjectValue(gameObjectValue, LuaManager.Instance.GlobalScript);
		}
	}
	[MoonSharpUserData]
	public class LuaScriptNumberValue : LuaScriptValue
	{
		public ScriptNumberValue ScriptNumberValue;

		public double Value
		{
			get
			{
				return ScriptNumberValue.Value;
			}
			set
			{
				ScriptNumberValue.Value = value;
			}
		}

		[MoonSharpHidden]
		public LuaScriptNumberValue(ScriptNumberValue value, Script script)
			: base(value, script)
		{
			ScriptNumberValue = value;
		}

		internal static LuaScriptNumberValue CastMethod(ScriptNumberValue numberValue)
		{
			return new LuaScriptNumberValue(numberValue, LuaManager.Instance.GlobalScript);
		}
	}
	[MoonSharpUserData]
	public class LuaScriptStringValue : LuaScriptValue
	{
		public ScriptStringValue ScriptStringValue;

		public string Value
		{
			get
			{
				return ScriptStringValue.Value;
			}
			set
			{
				ScriptStringValue.Value = value;
			}
		}

		[MoonSharpHidden]
		public LuaScriptStringValue(ScriptStringValue value, Script script)
			: base(value, script)
		{
			ScriptStringValue = value;
		}

		internal static LuaScriptStringValue CastMethod(ScriptStringValue stringValue)
		{
			return new LuaScriptStringValue(stringValue, LuaManager.Instance.GlobalScript);
		}
	}
	[MoonSharpUserData]
	public class LuaScriptValue : LuaBuiltInBehaviour
	{
		public ScriptValue ScriptValue;

		public string Name
		{
			get
			{
				return ScriptValue.Name;
			}
			set
			{
				ScriptValue.Name = value;
			}
		}

		[MoonSharpHidden]
		public LuaScriptValue(ScriptValue value, Script script)
			: base((Behaviour)(object)value, script)
		{
			ScriptValue = value;
		}
	}
	public static class LuaUtility
	{
		public static void OnInstantiate(GameObject gameObject)
		{
			ScriptBehavior[] componentsInChildren = gameObject.GetComponentsInChildren<ScriptBehavior>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].Restart();
			}
		}
	}
	public class PlayerLuaEngineComponent : MonoBehaviour
	{
		public bool AllowClimb = true;

		public LuaEventHandler OnLandCombo;

		public LuaEventHandler OnDropCombo;

		public Player Player;

		private void Awake()
		{
			OnLandCombo = new LuaEventHandler(LuaManager.Instance.GlobalScript);
			OnDropCombo = new LuaEventHandler(LuaManager.Instance.GlobalScript);
		}

		public static PlayerLuaEngineComponent Get(Player player)
		{
			return ((Component)player).gameObject.GetComponent<PlayerLuaEngineComponent>();
		}

		private void OnCollisionEnter(Collision collision)
		{
			ScriptBehavior[] componentsInParent = collision.gameObject.GetComponentsInParent<ScriptBehavior>();
			for (int i = 0; i < componentsInParent.Length; i++)
			{
				componentsInParent[i].OnPlayerCollisionEnter?.Invoke(new LuaPlayer(Player, LuaManager.Instance.GlobalScript));
			}
		}

		private void OnCollisionStay(Collision collision)
		{
			ScriptBehavior[] componentsInParent = collision.gameObject.GetComponentsInParent<ScriptBehavior>();
			for (int i = 0; i < componentsInParent.Length; i++)
			{
				componentsInParent[i].OnPlayerCollisionStay?.Invoke(new LuaPlayer(Player, LuaManager.Instance.GlobalScript));
			}
		}

		private void OnCollisionExit(Collision collision)
		{
			ScriptBehavior[] componentsInParent = collision.gameObject.GetComponentsInParent<ScriptBehavior>();
			for (int i = 0; i < componentsInParent.Length; i++)
			{
				componentsInParent[i].OnPlayerCollisionExit?.Invoke(new LuaPlayer(Player, LuaManager.Instance.GlobalScript));
			}
		}

		private void OnTriggerEnter(Collider other)
		{
			ScriptBehavior[] componentsInParent = ((Component)other).GetComponentsInParent<ScriptBehavior>();
			for (int i = 0; i < componentsInParent.Length; i++)
			{
				componentsInParent[i].OnPlayerTriggerEnter?.Invoke(new LuaPlayer(Player, LuaManager.Instance.GlobalScript));
			}
		}

		private void OnTriggerStay(Collider other)
		{
			ScriptBehavior[] componentsInParent = ((Component)other).GetComponentsInParent<ScriptBehavior>();
			for (int i = 0; i < componentsInParent.Length; i++)
			{
				componentsInParent[i].OnPlayerTriggerStay?.Invoke(new LuaPlayer(Player, LuaManager.Instance.GlobalScript));
			}
		}

		private void OnTriggerExit(Collider other)
		{
			ScriptBehavior[] componentsInParent = ((Component)other).GetComponentsInParent<ScriptBehavior>();
			for (int i = 0; i < componentsInParent.Length; i++)
			{
				componentsInParent[i].OnPlayerTriggerExit?.Invoke(new LuaPlayer(Player, LuaManager.Instance.GlobalScript));
			}
		}
	}
	[BepInPlugin("LuaEngine", "LuaEngine", "0.4.0")]
	public class Plugin : BaseUnityPlugin
	{
		private void Start()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				new Harmony("LuaEngine").PatchAll();
				LuaCastFactory.Initialize();
				LuaDatabase.Initialize(Paths.PluginPath);
				LuaManager.Create();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin LuaEngine 0.4.0 is loaded!");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("Plugin {0} {1} failed to load!{2}{3}", "LuaEngine", "0.4.0", Environment.NewLine, ex));
			}
		}
	}
	public class SequenceEvent : GameplayEvent
	{
		public PlayableDirector Director;

		public LuaEventHandler OnSequenceEnd;

		public override void Awake()
		{
			((AProgressable)this).Awake();
			OnSequenceEnd = new LuaEventHandler(LuaManager.Instance.GlobalScript);
		}

		public override void LetPlayerGo()
		{
			((GameplayEvent)this).LetPlayerGo();
			Director.time = Director.duration;
			Director.Evaluate();
			if ((Object)(object)WorldHandler.instance.CurrentCamera != (Object)(object)WorldHandler.instance.GetCurrentPlayer().cam.cam)
			{
				((Component)WorldHandler.instance.CurrentCamera).gameObject.SetActive(false);
			}
			OnSequenceEnd?.Invoke();
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "LuaEngine";

		public const string PLUGIN_NAME = "LuaEngine";

		public const string PLUGIN_VERSION = "0.4.0";
	}
}
namespace LuaEngine.Patches
{
	[HarmonyPatch(typeof(LedgeClimbAbility))]
	internal static class LedgeClimbAbilityPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("CheckActivation")]
		private static bool CheckActivation_Prefix(ref bool __result, LedgeClimbAbility __instance)
		{
			PlayerLuaEngineComponent playerLuaEngineComponent = PlayerLuaEngineComponent.Get(((Ability)__instance).p);
			if ((Object)(object)playerLuaEngineComponent == (Object)null)
			{
				return true;
			}
			if (playerLuaEngineComponent.AllowClimb)
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(Player))]
	internal static class PlayerPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Init")]
		private static void Init_Postfix(Player __instance)
		{
			if (!((Object)(object)((Component)__instance).gameObject.GetComponent<PlayerLuaEngineComponent>() != (Object)null))
			{
				((Component)__instance).gameObject.AddComponent<PlayerLuaEngineComponent>().Player = __instance;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("LandCombo")]
		private static void LandCombo_Prefix(Player __instance)
		{
			if (__instance.IsComboing())
			{
				PlayerLuaEngineComponent playerLuaEngineComponent = PlayerLuaEngineComponent.Get(__instance);
				if (!((Object)(object)playerLuaEngineComponent == (Object)null))
				{
					playerLuaEngineComponent.OnLandCombo?.Invoke();
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("DropCombo")]
		private static void DropCombo_Prefix(Player __instance)
		{
			if (__instance.IsComboing())
			{
				PlayerLuaEngineComponent playerLuaEngineComponent = PlayerLuaEngineComponent.Get(__instance);
				if (!((Object)(object)playerLuaEngineComponent == (Object)null))
				{
					playerLuaEngineComponent.OnDropCombo?.Invoke();
				}
			}
		}
	}
}
namespace LuaEngine.Mono
{
	public class ScriptBehavior : MonoBehaviour
	{
		public LuaEventHandler OnStart;

		public LuaEventHandler OnDestroyed;

		public LuaEventHandler OnAnyCollisionEnter;

		public LuaEventHandler OnAnyCollisionStay;

		public LuaEventHandler OnAnyCollisionExit;

		public LuaEventHandler OnPlayerCollisionEnter;

		public LuaEventHandler OnPlayerCollisionStay;

		public LuaEventHandler OnPlayerCollisionExit;

		public LuaEventHandler OnAnyTriggerEnter;

		public LuaEventHandler OnAnyTriggerStay;

		public LuaEventHandler OnAnyTriggerExit;

		public LuaEventHandler OnPlayerTriggerEnter;

		public LuaEventHandler OnPlayerTriggerStay;

		public LuaEventHandler OnPlayerTriggerExit;

		public string LuaScriptName;

		private bool _initialized;

		private void OnCollisionEnter(Collision collision)
		{
			OnAnyCollisionEnter?.Invoke(new LuaGameObject(collision.gameObject));
		}

		private void OnCollisionStay(Collision collision)
		{
			OnAnyCollisionStay?.Invoke(new LuaGameObject(collision.gameObject));
		}

		private void OnCollisionExit(Collision collision)
		{
			OnAnyCollisionExit?.Invoke(new LuaGameObject(collision.gameObject));
		}

		private void OnTriggerEnter(Collider other)
		{
			OnAnyTriggerEnter?.Invoke(new LuaGameObject(((Component)other).gameObject));
		}

		private void OnTriggerStay(Collider other)
		{
			OnAnyTriggerStay?.Invoke(new LuaGameObject(((Component)other).gameObject));
		}

		private void OnTriggerExit(Collider other)
		{
			OnAnyTriggerExit?.Invoke(new LuaGameObject(((Component)other).gameObject));
		}

		private void Awake()
		{
			Initialize();
		}

		private void OnEnable()
		{
			Initialize();
		}

		public void Initialize()
		{
			if (LuaScriptName != null && ((Component)this).gameObject.activeInHierarchy && !_initialized)
			{
				_initialized = true;
				Script globalScript = LuaManager.Instance.GlobalScript;
				LuaScript luaScript = LuaDatabase.BehaviorScripts[LuaScriptName];
				OnStart = new LuaEventHandler(globalScript);
				OnDestroyed = new LuaEventHandler(globalScript);
				OnAnyCollisionEnter = new LuaEventHandler(globalScript);
				OnAnyCollisionStay = new LuaEventHandler(globalScript);
				OnAnyCollisionExit = new LuaEventHandler(globalScript);
				OnPlayerCollisionEnter = new LuaEventHandler(globalScript);
				OnPlayerCollisionStay = new LuaEventHandler(globalScript);
				OnPlayerCollisionExit = new LuaEventHandler(globalScript);
				OnAnyTriggerEnter = new LuaEventHandler(globalScript);
				OnAnyTriggerStay = new LuaEventHandler(globalScript);
				OnAnyTriggerExit = new LuaEventHandler(globalScript);
				OnPlayerTriggerEnter = new LuaEventHandler(globalScript);
				OnPlayerTriggerStay = new LuaEventHandler(globalScript);
				OnPlayerTriggerExit = new LuaEventHandler(globalScript);
				luaScript.RunForScriptBehavior(globalScript, new LuaScriptBehavior(this, globalScript));
			}
		}

		public void Restart()
		{
			_initialized = false;
			Initialize();
		}

		private void OnDestroy()
		{
			OnDestroyed?.Invoke();
		}

		private void Start()
		{
			OnStart?.Invoke();
		}
	}
	public class ScriptComponentValue : ScriptValue
	{
		public Component Value;
	}
	public class ScriptGameObjectValue : ScriptValue
	{
		public GameObject Value;
	}
	public class ScriptNumberValue : ScriptValue
	{
		public double Value;
	}
	public class ScriptStringValue : ScriptValue
	{
		public string Value = "";
	}
	public abstract class ScriptValue : MonoBehaviour
	{
		public string Name = "";
	}
}
namespace LuaEngine.Modules
{
	public class LuaAlarmManager : ILuaModule
	{
		[MoonSharpUserData]
		public class LuaBindings
		{
			public string CreateAlarm(LuaGameObject gameObject, float seconds, bool runPaused, DynValue callback)
			{
				Alarm alarm = new Alarm();
				alarm.TimeLeft = seconds;
				alarm.RunPaused = runPaused;
				alarm.Callback.Add(callback);
				AlarmHandler alarmHandler = gameObject.Handle.GetComponent<AlarmHandler>();
				if ((Object)(object)alarmHandler == (Object)null)
				{
					alarmHandler = gameObject.Handle.AddComponent<AlarmHandler>();
				}
				return alarmHandler.Add(alarm);
			}

			public void RemoveAlarm(LuaGameObject gameObject, string guid)
			{
				AlarmHandler component = gameObject.Handle.GetComponent<AlarmHandler>();
				if (!((Object)(object)component == (Object)null))
				{
					component.Remove(guid);
				}
			}
		}

		private LuaBindings _bindings;

		public void OnRegister(Script script)
		{
			_bindings = new LuaBindings();
			script.Globals[(object)"AlarmManager"] = _bindings;
		}
	}
	public class LuaCore : ILuaModule
	{
		[MoonSharpUserData]
		public class LuaBindings
		{
			public LuaEventHandler OnAlwaysUpdate;

			public LuaEventHandler OnFixedUpdate;

			public LuaEventHandler OnUpdate;

			public LuaEventHandler OnLateUpdate;

			public string LuaEngineVersion => "0.4.0";

			public float DeltaTime => Core.dt;

			[MoonSharpHidden]
			public LuaBindings(Script script)
			{
				OnAlwaysUpdate = new LuaEventHandler(script);
				OnFixedUpdate = new LuaEventHandler(script);
				OnUpdate = new LuaEventHandler(script);
				OnLateUpdate = new LuaEventHandler(script);
			}
		}

		private LuaBindings _bindings;

		public void OnRegister(Script script)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			_bindings = new LuaBindings(script);
			Core.OnAlwaysUpdate += new OnUpdateHandler(Core_OnAlwaysUpdate);
			Core.OnFixedUpdate += new OnFixedUpdateHandler(Core_OnFixedUpdate);
			Core.OnUpdate += new OnUpdateHandler(Core_OnUpdate);
			Core.OnLateUpdate += new OnLateUpdateHandler(Core_OnLateUpdate);
			script.Globals[(object)"Core"] = _bindings;
		}

		private void Core_OnAlwaysUpdate()
		{
			_bindings.OnAlwaysUpdate.Invoke();
		}

		private void Core_OnFixedUpdate()
		{
			_bindings.OnFixedUpdate.Invoke();
		}

		private void Core_OnUpdate()
		{
			_bindings.OnUpdate.Invoke();
		}

		private void Core_OnLateUpdate()
		{
			_bindings.OnLateUpdate.Invoke();
		}
	}
	public class LuaSequenceHandler : ILuaModule
	{
		[MoonSharpUserData]
		public class LuaBindings
		{
			private LuaSequenceHandler _luaSequenceHandler;

			[MoonSharpHidden]
			public LuaBindings(LuaSequenceHandler luaSequenceHandler)
			{
				_luaSequenceHandler = luaSequenceHandler;
			}

			public void StartSequence(LuaPlayableDirector director, DynValue OnSequenceEnd = null, bool hidePlayer = true, bool interruptPlayer = true, bool instantly = false, bool pausePlayer = false, bool allowPhoneOnAfterSequence = true, bool skippable = true, bool lowerVolume = true)
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Invalid comparison between Unknown and I4
				SequenceEvent sequenceEvent = new GameObject("Lua Sequence Event").AddComponent<SequenceEvent>();
				sequenceEvent.Director = director.PlayableDirector;
				if (OnSequenceEnd != null && (int)OnSequenceEnd.Type == 5)
				{
					sequenceEvent.OnSequenceEnd.Add(OnSequenceEnd);
				}
				SequenceHandler.instance.StartEnteringSequence(director.PlayableDirector, (GameplayEvent)(object)sequenceEvent, hidePlayer, interruptPlayer, instantly, pausePlayer, allowPhoneOnAfterSequence, (ProgressObject)null, skippable, lowerVolume, (Battle)null, false);
			}
		}

		private LuaBindings _bindings;

		public void OnRegister(Script script)
		{
			_bindings = new LuaBindings(this);
			script.Globals[(object)"SequenceHandler"] = _bindings;
		}
	}
	public class LuaStageManager : ILuaModule
	{
		[MoonSharpUserData]
		public class LuaBindings
		{
			public LuaEventHandler OnStageInitialized;

			public LuaEventHandler OnStagePostInitialization;

			public int CurrentStage => (int)Utility.GetCurrentStage();

			[MoonSharpHidden]
			public LuaBindings(Script script)
			{
				OnStageInitialized = new LuaEventHandler(script);
				OnStagePostInitialization = new LuaEventHandler(script);
			}

			public void ExitCurrentStage(int targetStageID, int previousStageID)
			{
				Core.Instance.BaseModule.StageManager.ExitCurrentStage((Stage)targetStageID, (Stage)previousStageID);
			}

			public string GetInternalNameForStageID(int stageID)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				Stage val = (Stage)stageID;
				return ((object)(Stage)(ref val)).ToString();
			}

			public string GetLocalizedNameForStageID(int stageID)
			{
				return Core.Instance.Localizer.GetStageName((Stage)stageID);
			}

			public int GetStageIDForInternalName(string stageInternalName)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Expected I4, but got Unknown
				if (Enum.TryParse<Stage>(stageInternalName, out Stage result))
				{
					return (int)result;
				}
				return -1;
			}
		}

		private LuaBindings _bindings;

		public void OnRegister(Script script)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			_bindings = new LuaBindings(script);
			StageManager.OnStageInitialized += new OnStageInitializedDelegate(StageManager_OnStageInitialized);
			StageManager.OnStagePostInitialization += new OnStageInitializedDelegate(StageManager_OnStagePostInitialization);
			script.Globals[(object)"StageManager"] = _bindings;
		}

		private void StageManager_OnStageInitialized()
		{
			_bindings.OnStageInitialized.Invoke();
		}

		private void StageManager_OnStagePostInitialization()
		{
			_bindings.OnStagePostInitialization.Invoke();
		}
	}
	public class LuaUI : ILuaModule
	{
		[MoonSharpUserData]
		public class LuaBindings
		{
			private Script _script;

			[MoonSharpHidden]
			public LuaBindings(Script script)
			{
				_script = script;
			}

			public void SetTextMeshProText(LuaGameObject gameObject, string text)
			{
				gameObject.Handle.gameObject.GetComponent<TMP_Text>().text = text;
			}

			public string GetTextMeshProText(LuaGameObject gameObject)
			{
				return gameObject.Handle.gameObject.GetComponent<TMP_Text>().text;
			}

			public void StartScreenShake(string screenShakeType, float duration, bool continuous)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0053: Unknown result type (might be due to invalid IL or missing references)
				//IL_0068: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0063: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				ScreenShakeType val = (ScreenShakeType)0;
				switch (screenShakeType)
				{
				case "Light":
					val = (ScreenShakeType)0;
					break;
				case "Medium":
					val = (ScreenShakeType)1;
					break;
				case "Heavy":
					val = (ScreenShakeType)2;
					break;
				case "ExtraLight":
					val = (ScreenShakeType)3;
					break;
				case "JustABitLighter":
					val = (ScreenShakeType)4;
					break;
				case "UltraLight":
					val = (ScreenShakeType)5;
					break;
				}
				GameplayCamera.StartScreenShake(val, duration, continuous);
			}

			public void FadeInAndOut(float durationIn, float durationStay, float durationOut)
			{
				Core.Instance.BaseModule.uiManager.effects.FadeInAndOutBlack(durationIn, durationStay, durationOut, (UpdateType)3);
			}

			public void ShowNotification(string text)
			{
				Core.Instance.BaseModule.uiManager.ShowNotification(text, Array.Empty<string>());
			}

			public void ResetCamera()
			{
				GameplayCamera.instance.ResetCameraPositionRotation();
			}
		}

		private LuaBindings _bindings;

		public void OnRegister(Script script)
		{
			_bindings = new LuaBindings(script);
			script.Globals[(object)"UI"] = _bindings;
		}
	}
	public class LuaUnityEngine : ILuaModule
	{
		[MoonSharpUserData]
		public class LuaBindings
		{
			private Script _script;

			[MoonSharpHidden]
			public LuaBindings(Script script)
			{
				_script = script;
			}

			public List<LuaScriptBehavior> FindScriptBehaviors(string scriptName, bool includeInactive)
			{
				IEnumerable<ScriptBehavior> enumerable = from script in Object.FindObjectsOfType<ScriptBehavior>(includeInactive)
					where script.LuaScriptName == scriptName
					select script;
				List<LuaScriptBehavior> list = new List<LuaScriptBehavior>();
				foreach (ScriptBehavior item in enumerable)
				{
					list.Add(new LuaScriptBehavior(item, LuaManager.Instance.GlobalScript));
				}
				return list;
			}

			public List<LuaGameObject> GetGameObjects(bool includeInactive)
			{
				GameObject[] array = Object.FindObjectsOfType<GameObject>(includeInactive);
				List<LuaGameObject> list = new List<LuaGameObject>();
				GameObject[] array2 = array;
				foreach (GameObject handle in array2)
				{
					list.Add(new LuaGameObject(handle));
				}
				return list;
			}

			public LuaGameObject FindGameObjectByName(string name)
			{
				GameObject val = GameObject.Find(name);
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				return new LuaGameObject(val);
			}
		}

		private LuaBindings _bindings;

		public void OnRegister(Script script)
		{
			_bindings = new LuaBindings(script);
			script.Globals[(object)"Engine"] = _bindings;
			script.Globals[(object)"LuaGameObject"] = typeof(LuaGameObject);
		}
	}
	public class LuaWorldHandler : ILuaModule
	{
		[MoonSharpUserData]
		public class LuaBindings
		{
			private Script _script;

			public LuaGameObject CurrentCamera
			{
				get
				{
					WorldHandler instance = WorldHandler.instance;
					if ((Object)(object)instance == (Object)null)
					{
						return null;
					}
					return new LuaGameObject(((Component)instance.currentCamera).gameObject);
				}
			}

			public LuaPlayer CurrentPlayer
			{
				get
				{
					WorldHandler instance = WorldHandler.instance;
					if ((Object)(object)instance == (Object)null)
					{
						return null;
					}
					Player currentPlayer = instance.GetCurrentPlayer();
					if ((Object)(object)currentPlayer == (Object)null)
					{
						return null;
					}
					return new LuaPlayer(currentPlayer, _script);
				}
			}

			[MoonSharpHidden]
			public LuaBindings(Script script)
			{
				_script = script;
			}

			public void PlacePlayerAt(LuaPlayer player, Table luaPosition, Table luaEulerAngles, bool stopAbility = true)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = LuaMathUtils.TableToVector3(luaPosition);
				Quaternion val2 = Quaternion.Euler(LuaMathUtils.TableToVector3(luaEulerAngles));
				WorldHandler.instance.PlacePlayerAt(player.Player, val, val2, stopAbility);
			}
		}

		private LuaBindings _bindings;

		public void OnRegister(Script script)
		{
			_bindings = new LuaBindings(script);
			script.Globals[(object)"WorldHandler"] = _bindings;
		}
	}
}
namespace LuaEngine.MapStation
{
	public class LuaEngineGameMapStationPlugin : AGameMapStationPlugin
	{
		public override void OnReload()
		{
			LuaManager.Instance.Reload();
		}
	}
}
namespace LuaEngine.Alarms
{
	public class Alarm
	{
		public float TimeLeft;

		public bool RunPaused;

		public LuaEventHandler Callback;

		public Alarm()
		{
			Callback = new LuaEventHandler(LuaManager.Instance.GlobalScript);
		}
	}
	public class AlarmHandler : MonoBehaviour
	{
		public Dictionary<string, Alarm> AlarmByGUID;

		private void Awake()
		{
			AlarmByGUID = new Dictionary<string, Alarm>();
		}

		private void Update()
		{
			Dictionary<string, Alarm> dictionary = new Dictionary<string, Alarm>();
			foreach (KeyValuePair<string, Alarm> item in AlarmByGUID)
			{
				if (Core.Instance.IsCorePaused && !item.Value.RunPaused)
				{
					dictionary[item.Key] = item.Value;
					return;
				}
				item.Value.TimeLeft -= Core.dt;
				if (item.Value.TimeLeft <= 0f)
				{
					item.Value.Callback.Invoke();
					return;
				}
				dictionary[item.Key] = item.Value;
			}
			AlarmByGUID = dictionary;
		}

		public string Add(Alarm alarm)
		{
			string text = Guid.NewGuid().ToString();
			AlarmByGUID[text] = alarm;
			return text;
		}

		public void Remove(string guid)
		{
			if (AlarmByGUID.TryGetValue(guid, out var _))
			{
				AlarmByGUID.Remove(guid);
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}

MoonSharp.Interpreter.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using MoonSharp.Interpreter.Compatibility;
using MoonSharp.Interpreter.Compatibility.Frameworks;
using MoonSharp.Interpreter.CoreLib;
using MoonSharp.Interpreter.CoreLib.IO;
using MoonSharp.Interpreter.CoreLib.StringLib;
using MoonSharp.Interpreter.DataStructs;
using MoonSharp.Interpreter.Debugging;
using MoonSharp.Interpreter.Diagnostics;
using MoonSharp.Interpreter.Diagnostics.PerformanceCounters;
using MoonSharp.Interpreter.Execution;
using MoonSharp.Interpreter.Execution.Scopes;
using MoonSharp.Interpreter.Execution.VM;
using MoonSharp.Interpreter.IO;
using MoonSharp.Interpreter.Interop;
using MoonSharp.Interpreter.Interop.BasicDescriptors;
using MoonSharp.Interpreter.Interop.Converters;
using MoonSharp.Interpreter.Interop.LuaStateInterop;
using MoonSharp.Interpreter.Interop.RegistrationPolicies;
using MoonSharp.Interpreter.Interop.StandardDescriptors;
using MoonSharp.Interpreter.Interop.UserDataRegistries;
using MoonSharp.Interpreter.Loaders;
using MoonSharp.Interpreter.Platforms;
using MoonSharp.Interpreter.REPL;
using MoonSharp.Interpreter.Serialization.Json;
using MoonSharp.Interpreter.Tree;
using MoonSharp.Interpreter.Tree.Expressions;
using MoonSharp.Interpreter.Tree.Fast_Interface;
using MoonSharp.Interpreter.Tree.Statements;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("MoonSharp.Interpreter")]
[assembly: AssemblyDescription("An interpreter for the Lua language")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("http://www.moonsharp.org")]
[assembly: AssemblyProduct("MoonSharp.Interpreter")]
[assembly: AssemblyCopyright("Copyright © 2014-2015, Marco Mastropaolo")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c971e5a8-dbec-4408-8046-86e4fdd1b2e3")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: InternalsVisibleTo("MoonSharp.Interpreter.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100F704C50BBDC3F2F011CC26A8C6C4797A40E0B4BC94CFB1335E9BA208326340696B686DC13099F10D3054544532F5E3E66C26A13FF260AEA2343E0410511FE56EDCC2AFB898AAA1BC21DA33C0D0AE60824EB441D02A0E6B7AE251CDE0946BFC748209C12B062573ECDB008A3D10CC40534B314847591CE5342A3BC6AA83CE23B8")]
[assembly: InternalsVisibleTo("MoonSharp.Interpreter.Tests.net40-client, PublicKey=0024000004800000940000000602000000240000525341310004000001000100F704C50BBDC3F2F011CC26A8C6C4797A40E0B4BC94CFB1335E9BA208326340696B686DC13099F10D3054544532F5E3E66C26A13FF260AEA2343E0410511FE56EDCC2AFB898AAA1BC21DA33C0D0AE60824EB441D02A0E6B7AE251CDE0946BFC748209C12B062573ECDB008A3D10CC40534B314847591CE5342A3BC6AA83CE23B8")]
[assembly: InternalsVisibleTo("MoonSharp.Interpreter.Tests.portable40, PublicKey=0024000004800000940000000602000000240000525341310004000001000100F704C50BBDC3F2F011CC26A8C6C4797A40E0B4BC94CFB1335E9BA208326340696B686DC13099F10D3054544532F5E3E66C26A13FF260AEA2343E0410511FE56EDCC2AFB898AAA1BC21DA33C0D0AE60824EB441D02A0E6B7AE251CDE0946BFC748209C12B062573ECDB008A3D10CC40534B314847591CE5342A3BC6AA83CE23B8")]
[assembly: InternalsVisibleTo("MoonSharp.Interpreter.Tests.net35-client, PublicKey=0024000004800000940000000602000000240000525341310004000001000100F704C50BBDC3F2F011CC26A8C6C4797A40E0B4BC94CFB1335E9BA208326340696B686DC13099F10D3054544532F5E3E66C26A13FF260AEA2343E0410511FE56EDCC2AFB898AAA1BC21DA33C0D0AE60824EB441D02A0E6B7AE251CDE0946BFC748209C12B062573ECDB008A3D10CC40534B314847591CE5342A3BC6AA83CE23B8")]
[assembly: TargetFramework(".NETFramework,Version=v4.0,Profile=Client", FrameworkDisplayName = ".NET Framework 4 Client Profile")]
[assembly: AssemblyVersion("2.0.0.0")]
namespace MoonSharp.Interpreter
{
	public static class AsyncExtensions
	{
		private static Task<T> ExecAsync<T>(Func<T> func)
		{
			return Task.Factory.StartNew(func);
		}

		private static Task ExecAsyncVoid(Action func)
		{
			return Task.Factory.StartNew(func);
		}

		public static Task<DynValue> CallAsync(this Closure function)
		{
			return ExecAsync(() => function.Call());
		}

		public static Task<DynValue> CallAsync(this Closure function, params object[] args)
		{
			return ExecAsync(() => function.Call(args));
		}

		public static Task<DynValue> CallAsync(this Closure function, params DynValue[] args)
		{
			return ExecAsync(() => function.Call(args));
		}

		public static Task<DynValue> DoStringAsync(this Script script, string code, Table globalContext = null, string codeFriendlyName = null)
		{
			return ExecAsync(() => script.DoString(code, globalContext, codeFriendlyName));
		}

		public static Task<DynValue> DoStreamAsync(this Script script, Stream stream, Table globalContext = null, string codeFriendlyName = null)
		{
			return ExecAsync(() => script.DoStream(stream, globalContext, codeFriendlyName));
		}

		public static Task<DynValue> DoFileAsync(this Script script, string filename, Table globalContext = null, string codeFriendlyName = null)
		{
			return ExecAsync(() => script.DoFile(filename, globalContext, codeFriendlyName));
		}

		public static Task<DynValue> LoadFunctionAsync(this Script script, string code, Table globalTable = null, string funcFriendlyName = null)
		{
			return ExecAsync(() => script.LoadFunction(code, globalTable, funcFriendlyName));
		}

		public static Task<DynValue> LoadStringAsync(this Script script, string code, Table globalTable = null, string codeFriendlyName = null)
		{
			return ExecAsync(() => script.LoadString(code, globalTable, codeFriendlyName));
		}

		public static Task<DynValue> LoadStreamAsync(this Script script, Stream stream, Table globalTable = null, string codeFriendlyName = null)
		{
			return ExecAsync(() => script.LoadStream(stream, globalTable, codeFriendlyName));
		}

		public static Task DumpAsync(this Script script, DynValue function, Stream stream)
		{
			return ExecAsyncVoid(delegate
			{
				script.Dump(function, stream);
			});
		}

		public static Task<DynValue> LoadFileAsync(this Script script, string filename, Table globalContext = null, string friendlyFilename = null)
		{
			return ExecAsync(() => script.LoadFile(filename, globalContext, friendlyFilename));
		}

		public static Task<DynValue> CallAsync(this Script script, DynValue function)
		{
			return ExecAsync(() => script.Call(function));
		}

		public static Task<DynValue> CallAsync(this Script script, DynValue function, params DynValue[] args)
		{
			return ExecAsync(() => script.Call(function, args));
		}

		public static Task<DynValue> CallAsync(this Script script, DynValue function, params object[] args)
		{
			return ExecAsync(() => script.Call(function, args));
		}

		public static Task<DynValue> CallAsync(this Script script, object function)
		{
			return ExecAsync(() => script.Call(function));
		}

		public static Task<DynValue> CallAsync(this Script script, object function, params object[] args)
		{
			return ExecAsync(() => script.Call(function, args));
		}

		public static Task<DynamicExpression> CreateDynamicExpressionAsync(this Script script, string code)
		{
			return ExecAsync(() => script.CreateDynamicExpression(code));
		}

		public static Task<DynValue> EvaluateAsync(this ReplInterpreter interpreter, string input)
		{
			return ExecAsync(() => interpreter.Evaluate(input));
		}

		public static Task<DynValue> ResumeAsync(this Coroutine cor, params DynValue[] args)
		{
			return ExecAsync(() => cor.Resume(args));
		}

		public static Task<DynValue> ResumeAsync(this Coroutine cor, ScriptExecutionContext context, params DynValue[] args)
		{
			return ExecAsync(() => cor.Resume(context, args));
		}

		public static Task<DynValue> ResumeAsync(this Coroutine cor)
		{
			return ExecAsync(() => cor.Resume());
		}

		public static Task<DynValue> ResumeAsync(this Coroutine cor, ScriptExecutionContext context)
		{
			return ExecAsync(() => cor.Resume(context));
		}

		public static Task<DynValue> ResumeAsync(this Coroutine cor, params object[] args)
		{
			return ExecAsync(() => cor.Resume(args));
		}

		public static Task<DynValue> ResumeAsync(this Coroutine cor, ScriptExecutionContext context, params object[] args)
		{
			return ExecAsync(() => cor.Resume(context, args));
		}
	}
	[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = true)]
	public sealed class MoonSharpPropertyAttribute : Attribute
	{
		public string Name { get; private set; }

		public MoonSharpPropertyAttribute()
		{
		}

		public MoonSharpPropertyAttribute(string name)
		{
			Name = name;
		}
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
	public sealed class MoonSharpUserDataMetamethodAttribute : Attribute
	{
		public string Name { get; private set; }

		public MoonSharpUserDataMetamethodAttribute(string name)
		{
			Name = name;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = true, AllowMultiple = true)]
	public sealed class MoonSharpHideMemberAttribute : Attribute
	{
		public string MemberName { get; private set; }

		public MoonSharpHideMemberAttribute(string memberName)
		{
			MemberName = memberName;
		}
	}
	[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event, Inherited = true, AllowMultiple = false)]
	public sealed class MoonSharpHiddenAttribute : Attribute
	{
	}
	public delegate object ScriptFunctionDelegate(params object[] args);
	public delegate T ScriptFunctionDelegate<T>(params object[] args);
	[Flags]
	public enum TypeValidationFlags
	{
		None = 0,
		AllowNil = 1,
		AutoConvert = 2,
		Default = 2
	}
	[Serializable]
	public class DynamicExpressionException : ScriptRuntimeException
	{
		public DynamicExpressionException(string format, params object[] args)
			: base("<dynamic>: " + format, args)
		{
		}

		public DynamicExpressionException(string message)
			: base("<dynamic>: " + message)
		{
		}
	}
	public class DynamicExpression : IScriptPrivateResource
	{
		private DynamicExprExpression m_Exp;

		private DynValue m_Constant;

		public readonly string ExpressionCode;

		public Script OwnerScript { get; private set; }

		internal DynamicExpression(Script S, string strExpr, DynamicExprExpression expr)
		{
			ExpressionCode = strExpr;
			OwnerScript = S;
			m_Exp = expr;
		}

		internal DynamicExpression(Script S, string strExpr, DynValue constant)
		{
			ExpressionCode = strExpr;
			OwnerScript = S;
			m_Constant = constant;
		}

		public DynValue Evaluate(ScriptExecutionContext context = null)
		{
			context = context ?? OwnerScript.CreateDynamicExecutionContext();
			this.CheckScriptOwnership(context.GetScript());
			if (m_Constant != null)
			{
				return m_Constant;
			}
			return m_Exp.Eval(context);
		}

		public SymbolRef FindSymbol(ScriptExecutionContext context)
		{
			this.CheckScriptOwnership(context.GetScript());
			if (m_Exp != null)
			{
				return m_Exp.FindDynamic(context);
			}
			return null;
		}

		public bool IsConstant()
		{
			return m_Constant != null;
		}

		public override int GetHashCode()
		{
			return ExpressionCode.GetHashCode();
		}

		public override bool Equals(object obj)
		{
			if (!(obj is DynamicExpression dynamicExpression))
			{
				return false;
			}
			return dynamicExpression.ExpressionCode == ExpressionCode;
		}
	}
	internal static class Extension_Methods
	{
		public static TValue GetOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
		{
			if (dictionary.TryGetValue(key, out var value))
			{
				return value;
			}
			return default(TValue);
		}

		public static TValue GetOrCreate<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, Func<TValue> creator)
		{
			if (!dictionary.TryGetValue(key, out var value))
			{
				value = creator();
				dictionary.Add(key, value);
			}
			return value;
		}
	}
	public class Coroutine : RefIdObject, IScriptPrivateResource
	{
		public enum CoroutineType
		{
			Coroutine,
			ClrCallback,
			ClrCallbackDead
		}

		private CallbackFunction m_ClrCallback;

		private Processor m_Processor;

		public CoroutineType Type { get; private set; }

		public CoroutineState State
		{
			get
			{
				if (Type == CoroutineType.ClrCallback)
				{
					return CoroutineState.NotStarted;
				}
				if (Type == CoroutineType.ClrCallbackDead)
				{
					return CoroutineState.Dead;
				}
				return m_Processor.State;
			}
		}

		public Script OwnerScript { get; private set; }

		public long AutoYieldCounter
		{
			get
			{
				return m_Processor.AutoYieldCounter;
			}
			set
			{
				m_Processor.AutoYieldCounter = value;
			}
		}

		internal Coroutine(CallbackFunction function)
		{
			Type = CoroutineType.ClrCallback;
			m_ClrCallback = function;
			OwnerScript = null;
		}

		internal Coroutine(Processor proc)
		{
			Type = CoroutineType.Coroutine;
			m_Processor = proc;
			m_Processor.AssociatedCoroutine = this;
			OwnerScript = proc.GetScript();
		}

		internal void MarkClrCallbackAsDead()
		{
			if (Type != CoroutineType.ClrCallback)
			{
				throw new InvalidOperationException("State must be CoroutineType.ClrCallback");
			}
			Type = CoroutineType.ClrCallbackDead;
		}

		public IEnumerable<DynValue> AsTypedEnumerable()
		{
			if (Type != 0)
			{
				throw new InvalidOperationException("Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead");
			}
			while (State == CoroutineState.NotStarted || State == CoroutineState.Suspended || State == CoroutineState.ForceSuspended)
			{
				yield return Resume();
			}
		}

		public IEnumerable<object> AsEnumerable()
		{
			foreach (DynValue item in AsTypedEnumerable())
			{
				yield return item.ToScalar().ToObject();
			}
		}

		public IEnumerable<T> AsEnumerable<T>()
		{
			foreach (DynValue item in AsTypedEnumerable())
			{
				yield return item.ToScalar().ToObject<T>();
			}
		}

		public IEnumerator AsUnityCoroutine()
		{
			foreach (DynValue item in AsTypedEnumerable())
			{
				_ = item;
				yield return null;
			}
		}

		public DynValue Resume(params DynValue[] args)
		{
			this.CheckScriptOwnership(args);
			if (Type == CoroutineType.Coroutine)
			{
				return m_Processor.Coroutine_Resume(args);
			}
			throw new InvalidOperationException("Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead");
		}

		public DynValue Resume(ScriptExecutionContext context, params DynValue[] args)
		{
			this.CheckScriptOwnership(context);
			this.CheckScriptOwnership(args);
			if (Type == CoroutineType.Coroutine)
			{
				return m_Processor.Coroutine_Resume(args);
			}
			if (Type == CoroutineType.ClrCallback)
			{
				DynValue result = m_ClrCallback.Invoke(context, args);
				MarkClrCallbackAsDead();
				return result;
			}
			throw ScriptRuntimeException.CannotResumeNotSuspended(CoroutineState.Dead);
		}

		public DynValue Resume()
		{
			return Resume(new DynValue[0]);
		}

		public DynValue Resume(ScriptExecutionContext context)
		{
			return Resume(context, new DynValue[0]);
		}

		public DynValue Resume(params object[] args)
		{
			if (Type != 0)
			{
				throw new InvalidOperationException("Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead");
			}
			DynValue[] array = new DynValue[args.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = DynValue.FromObject(OwnerScript, args[i]);
			}
			return Resume(array);
		}

		public DynValue Resume(ScriptExecutionContext context, params object[] args)
		{
			DynValue[] array = new DynValue[args.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = DynValue.FromObject(context.GetScript(), args[i]);
			}
			return Resume(context, array);
		}

		public WatchItem[] GetStackTrace(int skip, SourceRef entrySourceRef = null)
		{
			if (State != CoroutineState.Running)
			{
				entrySourceRef = m_Processor.GetCoroutineSuspendedLocation();
			}
			return m_Processor.Debugger_GetCallStack(entrySourceRef).Skip(skip).ToArray();
		}
	}
	public interface IScriptPrivateResource
	{
		Script OwnerScript { get; }
	}
	internal static class ScriptPrivateResource_Extension
	{
		public static void CheckScriptOwnership(this IScriptPrivateResource containingResource, DynValue[] values)
		{
			foreach (DynValue value in values)
			{
				containingResource.CheckScriptOwnership(value);
			}
		}

		public static void CheckScriptOwnership(this IScriptPrivateResource containingResource, DynValue value)
		{
			if (value != null)
			{
				IScriptPrivateResource asPrivateResource = value.GetAsPrivateResource();
				if (asPrivateResource != null)
				{
					containingResource.CheckScriptOwnership(asPrivateResource);
				}
			}
		}

		public static void CheckScriptOwnership(this IScriptPrivateResource resource, Script script)
		{
			if (resource.OwnerScript != null && resource.OwnerScript != script && script != null)
			{
				throw new ScriptRuntimeException("Attempt to access a resource owned by a script, from another script");
			}
		}

		public static void CheckScriptOwnership(this IScriptPrivateResource containingResource, IScriptPrivateResource itemResource)
		{
			if (itemResource != null)
			{
				if (containingResource.OwnerScript != null && containingResource.OwnerScript != itemResource.OwnerScript && itemResource.OwnerScript != null)
				{
					throw new ScriptRuntimeException("Attempt to perform operations with resources owned by different scripts.");
				}
				if (containingResource.OwnerScript == null && itemResource.OwnerScript != null)
				{
					throw new ScriptRuntimeException("Attempt to perform operations with a script private resource on a shared resource.");
				}
			}
		}
	}
	public class RefIdObject
	{
		private static int s_RefIDCounter;

		private int m_RefID = ++s_RefIDCounter;

		public int ReferenceID => m_RefID;

		public string FormatTypeString(string typeString)
		{
			return $"{typeString}: {m_RefID:X8}";
		}
	}
	public class TailCallData
	{
		public DynValue Function { get; set; }

		public DynValue[] Args { get; set; }

		public CallbackFunction Continuation { get; set; }

		public CallbackFunction ErrorHandler { get; set; }

		public DynValue ErrorHandlerBeforeUnwind { get; set; }
	}
	public class UserData : RefIdObject
	{
		public DynValue UserValue { get; set; }

		public object Object { get; private set; }

		public IUserDataDescriptor Descriptor { get; private set; }

		public static IRegistrationPolicy RegistrationPolicy
		{
			get
			{
				return TypeDescriptorRegistry.RegistrationPolicy;
			}
			set
			{
				TypeDescriptorRegistry.RegistrationPolicy = value;
			}
		}

		public static InteropAccessMode DefaultAccessMode
		{
			get
			{
				return TypeDescriptorRegistry.DefaultAccessMode;
			}
			set
			{
				TypeDescriptorRegistry.DefaultAccessMode = value;
			}
		}

		private UserData()
		{
		}

		static UserData()
		{
			RegistrationPolicy = InteropRegistrationPolicy.Default;
			RegisterType<EventFacade>(InteropAccessMode.NoReflectionAllowed);
			RegisterType<AnonWrapper>(InteropAccessMode.HideMembers);
			RegisterType<EnumerableWrapper>(InteropAccessMode.NoReflectionAllowed);
			RegisterType<JsonNull>(InteropAccessMode.Reflection);
			DefaultAccessMode = InteropAccessMode.LazyOptimized;
		}

		public static IUserDataDescriptor RegisterType<T>(InteropAccessMode accessMode = InteropAccessMode.Default, string friendlyName = null)
		{
			return TypeDescriptorRegistry.RegisterType_Impl(typeof(T), accessMode, friendlyName, null);
		}

		public static IUserDataDescriptor RegisterType(Type type, InteropAccessMode accessMode = InteropAccessMode.Default, string friendlyName = null)
		{
			return TypeDescriptorRegistry.RegisterType_Impl(type, accessMode, friendlyName, null);
		}

		public static IUserDataDescriptor RegisterProxyType(IProxyFactory proxyFactory, InteropAccessMode accessMode = InteropAccessMode.Default, string friendlyName = null)
		{
			return TypeDescriptorRegistry.RegisterProxyType_Impl(proxyFactory, accessMode, friendlyName);
		}

		public static IUserDataDescriptor RegisterProxyType<TProxy, TTarget>(Func<TTarget, TProxy> wrapDelegate, InteropAccessMode accessMode = InteropAccessMode.Default, string friendlyName = null) where TProxy : class where TTarget : class
		{
			return RegisterProxyType(new DelegateProxyFactory<TProxy, TTarget>(wrapDelegate), accessMode, friendlyName);
		}

		public static IUserDataDescriptor RegisterType<T>(IUserDataDescriptor customDescriptor)
		{
			return TypeDescriptorRegistry.RegisterType_Impl(typeof(T), InteropAccessMode.Default, null, customDescriptor);
		}

		public static IUserDataDescriptor RegisterType(Type type, IUserDataDescriptor customDescriptor)
		{
			return TypeDescriptorRegistry.RegisterType_Impl(type, InteropAccessMode.Default, null, customDescriptor);
		}

		public static IUserDataDescriptor RegisterType(IUserDataDescriptor customDescriptor)
		{
			return TypeDescriptorRegistry.RegisterType_Impl(customDescriptor.Type, InteropAccessMode.Default, null, customDescriptor);
		}

		public static void RegisterAssembly(Assembly asm = null, bool includeExtensionTypes = false)
		{
			if (asm == null)
			{
				asm = Assembly.GetCallingAssembly();
			}
			TypeDescriptorRegistry.RegisterAssembly(asm, includeExtensionTypes);
		}

		public static bool IsTypeRegistered(Type t)
		{
			return TypeDescriptorRegistry.IsTypeRegistered(t);
		}

		public static bool IsTypeRegistered<T>()
		{
			return TypeDescriptorRegistry.IsTypeRegistered(typeof(T));
		}

		public static void UnregisterType<T>()
		{
			TypeDescriptorRegistry.UnregisterType(typeof(T));
		}

		public static void UnregisterType(Type t)
		{
			TypeDescriptorRegistry.UnregisterType(t);
		}

		public static DynValue Create(object o, IUserDataDescriptor descr)
		{
			return DynValue.NewUserData(new UserData
			{
				Descriptor = descr,
				Object = o
			});
		}

		public static DynValue Create(object o)
		{
			IUserDataDescriptor descriptorForObject = GetDescriptorForObject(o);
			if (descriptorForObject == null)
			{
				if (o is Type)
				{
					return CreateStatic((Type)o);
				}
				return null;
			}
			return Create(o, descriptorForObject);
		}

		public static DynValue CreateStatic(IUserDataDescriptor descr)
		{
			if (descr == null)
			{
				return null;
			}
			return DynValue.NewUserData(new UserData
			{
				Descriptor = descr,
				Object = null
			});
		}

		public static DynValue CreateStatic(Type t)
		{
			return CreateStatic(GetDescriptorForType(t, searchInterfaces: false));
		}

		public static DynValue CreateStatic<T>()
		{
			return CreateStatic(GetDescriptorForType(typeof(T), searchInterfaces: false));
		}

		public static void RegisterExtensionType(Type type, InteropAccessMode mode = InteropAccessMode.Default)
		{
			ExtensionMethodsRegistry.RegisterExtensionType(type, mode);
		}

		public static List<IOverloadableMemberDescriptor> GetExtensionMethodsByNameAndType(string name, Type extendedType)
		{
			return ExtensionMethodsRegistry.GetExtensionMethodsByNameAndType(name, extendedType);
		}

		public static int GetExtensionMethodsChangeVersion()
		{
			return ExtensionMethodsRegistry.GetExtensionMethodsChangeVersion();
		}

		public static IUserDataDescriptor GetDescriptorForType<T>(bool searchInterfaces)
		{
			return TypeDescriptorRegistry.GetDescriptorForType(typeof(T), searchInterfaces);
		}

		public static IUserDataDescriptor GetDescriptorForType(Type type, bool searchInterfaces)
		{
			return TypeDescriptorRegistry.GetDescriptorForType(type, searchInterfaces);
		}

		public static IUserDataDescriptor GetDescriptorForObject(object o)
		{
			return TypeDescriptorRegistry.GetDescriptorForType(o.GetType(), searchInterfaces: true);
		}

		public static Table GetDescriptionOfRegisteredTypes(bool useHistoricalData = false)
		{
			DynValue dynValue = DynValue.NewPrimeTable();
			foreach (KeyValuePair<Type, IUserDataDescriptor> item in useHistoricalData ? TypeDescriptorRegistry.RegisteredTypesHistory : TypeDescriptorRegistry.RegisteredTypes)
			{
				if (item.Value is IWireableDescriptor wireableDescriptor)
				{
					DynValue dynValue2 = DynValue.NewPrimeTable();
					dynValue.Table.Set(item.Key.FullName, dynValue2);
					wireableDescriptor.PrepareForWiring(dynValue2.Table);
				}
			}
			return dynValue.Table;
		}

		public static IEnumerable<Type> GetRegisteredTypes(bool useHistoricalData = false)
		{
			return (useHistoricalData ? TypeDescriptorRegistry.RegisteredTypesHistory : TypeDescriptorRegistry.RegisteredTypes).Select((KeyValuePair<Type, IUserDataDescriptor> p) => p.Value.Type);
		}
	}
	public static class WellKnownSymbols
	{
		public const string VARARGS = "...";

		public const string ENV = "_ENV";
	}
	public class YieldRequest
	{
		public DynValue[] ReturnValues;

		public bool Forced { get; internal set; }
	}
	[Serializable]
	public class ScriptRuntimeException : InterpreterException
	{
		public ScriptRuntimeException(Exception ex)
			: base(ex)
		{
		}

		public ScriptRuntimeException(ScriptRuntimeException ex)
			: base(ex, ex.DecoratedMessage)
		{
			base.DecoratedMessage = Message;
			base.DoNotDecorateMessage = true;
		}

		public ScriptRuntimeException(string message)
			: base(message)
		{
		}

		public ScriptRuntimeException(string format, params object[] args)
			: base(format, args)
		{
		}

		public static ScriptRuntimeException ArithmeticOnNonNumber(DynValue l, DynValue r = null)
		{
			if (l.Type != DataType.Number && l.Type != DataType.String)
			{
				return new ScriptRuntimeException("attempt to perform arithmetic on a {0} value", l.Type.ToLuaTypeString());
			}
			if (r != null && r.Type != DataType.Number && r.Type != DataType.String)
			{
				return new ScriptRuntimeException("attempt to perform arithmetic on a {0} value", r.Type.ToLuaTypeString());
			}
			if (l.Type == DataType.String || (r != null && r.Type == DataType.String))
			{
				return new ScriptRuntimeException("attempt to perform arithmetic on a string value");
			}
			throw new InternalErrorException("ArithmeticOnNonNumber - both are numbers");
		}

		public static ScriptRuntimeException ConcatOnNonString(DynValue l, DynValue r)
		{
			if (l.Type != DataType.Number && l.Type != DataType.String)
			{
				return new ScriptRuntimeException("attempt to concatenate a {0} value", l.Type.ToLuaTypeString());
			}
			if (r != null && r.Type != DataType.Number && r.Type != DataType.String)
			{
				return new ScriptRuntimeException("attempt to concatenate a {0} value", r.Type.ToLuaTypeString());
			}
			throw new InternalErrorException("ConcatOnNonString - both are numbers/strings");
		}

		public static ScriptRuntimeException LenOnInvalidType(DynValue r)
		{
			return new ScriptRuntimeException("attempt to get length of a {0} value", r.Type.ToLuaTypeString());
		}

		public static ScriptRuntimeException CompareInvalidType(DynValue l, DynValue r)
		{
			if (l.Type.ToLuaTypeString() == r.Type.ToLuaTypeString())
			{
				return new ScriptRuntimeException("attempt to compare two {0} values", l.Type.ToLuaTypeString());
			}
			return new ScriptRuntimeException("attempt to compare {0} with {1}", l.Type.ToLuaTypeString(), r.Type.ToLuaTypeString());
		}

		public static ScriptRuntimeException BadArgument(int argNum, string funcName, string message)
		{
			return new ScriptRuntimeException("bad argument #{0} to '{1}' ({2})", argNum + 1, funcName, message);
		}

		public static ScriptRuntimeException BadArgumentUserData(int argNum, string funcName, Type expected, object got, bool allowNil)
		{
			return new ScriptRuntimeException("bad argument #{0} to '{1}' (userdata<{2}>{3} expected, got {4})", argNum + 1, funcName, expected.Name, allowNil ? "nil or " : "", (got != null) ? ("userdata<" + got.GetType().Name + ">") : "null");
		}

		public static ScriptRuntimeException BadArgument(int argNum, string funcName, DataType expected, DataType got, bool allowNil)
		{
			return BadArgument(argNum, funcName, expected.ToErrorTypeString(), got.ToErrorTypeString(), allowNil);
		}

		public static ScriptRuntimeException BadArgument(int argNum, string funcName, string expected, string got, bool allowNil)
		{
			return new ScriptRuntimeException("bad argument #{0} to '{1}' ({2}{3} expected, got {4})", argNum + 1, funcName, allowNil ? "nil or " : "", expected, got);
		}

		public static ScriptRuntimeException BadArgumentNoValue(int argNum, string funcName, DataType expected)
		{
			return new ScriptRuntimeException("bad argument #{0} to '{1}' ({2} expected, got no value)", argNum + 1, funcName, expected.ToErrorTypeString());
		}

		public static ScriptRuntimeException BadArgumentIndexOutOfRange(string funcName, int argNum)
		{
			return new ScriptRuntimeException("bad argument #{0} to '{1}' (index out of range)", argNum + 1, funcName);
		}

		public static ScriptRuntimeException BadArgumentNoNegativeNumbers(int argNum, string funcName)
		{
			return new ScriptRuntimeException("bad argument #{0} to '{1}' (not a non-negative number in proper range)", argNum + 1, funcName);
		}

		public static ScriptRuntimeException BadArgumentValueExpected(int argNum, string funcName)
		{
			return new ScriptRuntimeException("bad argument #{0} to '{1}' (value expected)", argNum + 1, funcName);
		}

		public static ScriptRuntimeException IndexType(DynValue obj)
		{
			return new ScriptRuntimeException("attempt to index a {0} value", obj.Type.ToLuaTypeString());
		}

		public static ScriptRuntimeException LoopInIndex()
		{
			return new ScriptRuntimeException("loop in gettable");
		}

		public static ScriptRuntimeException LoopInNewIndex()
		{
			return new ScriptRuntimeException("loop in settable");
		}

		public static ScriptRuntimeException LoopInCall()
		{
			return new ScriptRuntimeException("loop in call");
		}

		public static ScriptRuntimeException TableIndexIsNil()
		{
			return new ScriptRuntimeException("table index is nil");
		}

		public static ScriptRuntimeException TableIndexIsNaN()
		{
			return new ScriptRuntimeException("table index is NaN");
		}

		public static ScriptRuntimeException ConvertToNumberFailed(int stage)
		{
			return stage switch
			{
				1 => new ScriptRuntimeException("'for' initial value must be a number"), 
				2 => new ScriptRuntimeException("'for' step must be a number"), 
				3 => new ScriptRuntimeException("'for' limit must be a number"), 
				_ => new ScriptRuntimeException("value must be a number"), 
			};
		}

		public static ScriptRuntimeException ConvertObjectFailed(object obj)
		{
			return new ScriptRuntimeException("cannot convert clr type {0}", obj.GetType());
		}

		public static ScriptRuntimeException ConvertObjectFailed(DataType t)
		{
			return new ScriptRuntimeException("cannot convert a {0} to a clr type", t.ToString().ToLowerInvariant());
		}

		public static ScriptRuntimeException ConvertObjectFailed(DataType t, Type t2)
		{
			return new ScriptRuntimeException("cannot convert a {0} to a clr type {1}", t.ToString().ToLowerInvariant(), t2.FullName);
		}

		public static ScriptRuntimeException UserDataArgumentTypeMismatch(DataType t, Type clrType)
		{
			return new ScriptRuntimeException("cannot find a conversion from a MoonSharp {0} to a clr {1}", t.ToString().ToLowerInvariant(), clrType.FullName);
		}

		public static ScriptRuntimeException UserDataMissingField(string typename, string fieldname)
		{
			return new ScriptRuntimeException("cannot access field {0} of userdata<{1}>", fieldname, typename);
		}

		public static ScriptRuntimeException CannotResumeNotSuspended(CoroutineState state)
		{
			if (state == CoroutineState.Dead)
			{
				return new ScriptRuntimeException("cannot resume dead coroutine");
			}
			return new ScriptRuntimeException("cannot resume non-suspended coroutine");
		}

		public static ScriptRuntimeException CannotYield()
		{
			return new ScriptRuntimeException("attempt to yield across a CLR-call boundary");
		}

		public static ScriptRuntimeException CannotYieldMain()
		{
			return new ScriptRuntimeException("attempt to yield from outside a coroutine");
		}

		public static ScriptRuntimeException AttemptToCallNonFunc(DataType type, string debugText = null)
		{
			string text = type.ToErrorTypeString();
			if (debugText != null)
			{
				return new ScriptRuntimeException("attempt to call a {0} value near '{1}'", text, debugText);
			}
			return new ScriptRuntimeException("attempt to call a {0} value", text);
		}

		public static ScriptRuntimeException AccessInstanceMemberOnStatics(IMemberDescriptor desc)
		{
			return new ScriptRuntimeException("attempt to access instance member {0} from a static userdata", desc.Name);
		}

		public static ScriptRuntimeException AccessInstanceMemberOnStatics(IUserDataDescriptor typeDescr, IMemberDescriptor desc)
		{
			return new ScriptRuntimeException("attempt to access instance member {0}.{1} from a static userdata", typeDescr.Name, desc.Name);
		}

		public override void Rethrow()
		{
			if (Script.GlobalOptions.RethrowExceptionNested)
			{
				throw new ScriptRuntimeException(this);
			}
		}
	}
	[Serializable]
	public class InternalErrorException : InterpreterException
	{
		internal InternalErrorException(string message)
			: base(message)
		{
		}

		internal InternalErrorException(string format, params object[] args)
			: base(format, args)
		{
		}
	}
	[Serializable]
	public class InterpreterException : Exception
	{
		public int InstructionPtr { get; internal set; }

		public IList<WatchItem> CallStack { get; internal set; }

		public string DecoratedMessage { get; internal set; }

		public bool DoNotDecorateMessage { get; set; }

		protected InterpreterException(Exception ex, string message)
			: base(message, ex)
		{
		}

		protected InterpreterException(Exception ex)
			: base(ex.Message, ex)
		{
		}

		protected InterpreterException(string message)
			: base(message)
		{
		}

		protected InterpreterException(string format, params object[] args)
			: base(string.Format(format, args))
		{
		}

		internal void DecorateMessage(Script script, SourceRef sref, int ip = -1)
		{
			if (string.IsNullOrEmpty(DecoratedMessage))
			{
				if (DoNotDecorateMessage)
				{
					DecoratedMessage = Message;
				}
				else if (sref != null)
				{
					DecoratedMessage = $"{sref.FormatLocation(script)}: {Message}";
				}
				else
				{
					DecoratedMessage = $"bytecode:{ip}: {Message}";
				}
			}
		}

		public virtual void Rethrow()
		{
		}
	}
	[Serializable]
	public class SyntaxErrorException : InterpreterException
	{
		internal Token Token { get; private set; }

		public bool IsPrematureStreamTermination { get; set; }

		internal SyntaxErrorException(Token t, string format, params object[] args)
			: base(format, args)
		{
			Token = t;
		}

		internal SyntaxErrorException(Token t, string message)
			: base(message)
		{
			Token = t;
		}

		internal SyntaxErrorException(Script script, SourceRef sref, string format, params object[] args)
			: base(format, args)
		{
			DecorateMessage(script, sref);
		}

		internal SyntaxErrorException(Script script, SourceRef sref, string message)
			: base(message)
		{
			DecorateMessage(script, sref);
		}

		private SyntaxErrorException(SyntaxErrorException syntaxErrorException)
			: base(syntaxErrorException, syntaxErrorException.DecoratedMessage)
		{
			Token = syntaxErrorException.Token;
			base.DecoratedMessage = Message;
		}

		internal void DecorateMessage(Script script)
		{
			if (Token != null)
			{
				DecorateMessage(script, Token.GetSourceRef(isStepStop: false));
			}
		}

		public override void Rethrow()
		{
			if (Script.GlobalOptions.RethrowExceptionNested)
			{
				throw new SyntaxErrorException(this);
			}
		}
	}
	public class CallbackArguments
	{
		private IList<DynValue> m_Args;

		private int m_Count;

		private bool m_LastIsTuple;

		public int Count => m_Count;

		public bool IsMethodCall { get; private set; }

		public DynValue this[int index] => RawGet(index, translateVoids: true) ?? DynValue.Void;

		public CallbackArguments(IList<DynValue> args, bool isMethodCall)
		{
			m_Args = args;
			if (m_Args.Count > 0)
			{
				DynValue dynValue = m_Args[m_Args.Count - 1];
				if (dynValue.Type == DataType.Tuple)
				{
					m_Count = dynValue.Tuple.Length - 1 + m_Args.Count;
					m_LastIsTuple = true;
				}
				else if (dynValue.Type == DataType.Void)
				{
					m_Count = m_Args.Count - 1;
				}
				else
				{
					m_Count = m_Args.Count;
				}
			}
			else
			{
				m_Count = 0;
			}
			IsMethodCall = isMethodCall;
		}

		public DynValue RawGet(int index, bool translateVoids)
		{
			if (index >= m_Count)
			{
				return null;
			}
			DynValue dynValue = ((m_LastIsTuple && index >= m_Args.Count - 1) ? m_Args[m_Args.Count - 1].Tuple[index - (m_Args.Count - 1)] : m_Args[index]);
			if (dynValue.Type == DataType.Tuple)
			{
				dynValue = ((dynValue.Tuple.Length == 0) ? DynValue.Nil : dynValue.Tuple[0]);
			}
			if (translateVoids && dynValue.Type == DataType.Void)
			{
				dynValue = DynValue.Nil;
			}
			return dynValue;
		}

		public DynValue[] GetArray(int skip = 0)
		{
			if (skip >= m_Count)
			{
				return new DynValue[0];
			}
			DynValue[] array = new DynValue[m_Count - skip];
			for (int i = skip; i < m_Count; i++)
			{
				array[i - skip] = this[i];
			}
			return array;
		}

		public DynValue AsType(int argNum, string funcName, DataType type, bool allowNil = false)
		{
			return this[argNum].CheckType(funcName, type, argNum, allowNil ? (TypeValidationFlags.AllowNil | TypeValidationFlags.AutoConvert) : TypeValidationFlags.AutoConvert);
		}

		public T AsUserData<T>(int argNum, string funcName, bool allowNil = false)
		{
			return this[argNum].CheckUserDataType<T>(funcName, argNum, allowNil ? TypeValidationFlags.AllowNil : TypeValidationFlags.None);
		}

		public int AsInt(int argNum, string funcName)
		{
			return (int)AsType(argNum, funcName, DataType.Number).Number;
		}

		public long AsLong(int argNum, string funcName)
		{
			return (long)AsType(argNum, funcName, DataType.Number).Number;
		}

		public string AsStringUsingMeta(ScriptExecutionContext executionContext, int argNum, string funcName)
		{
			if (this[argNum].Type == DataType.Table && this[argNum].Table.MetaTable != null && this[argNum].Table.MetaTable.RawGet("__tostring") != null)
			{
				DynValue dynValue = executionContext.GetScript().Call(this[argNum].Table.MetaTable.RawGet("__tostring"), this[argNum]);
				if (dynValue.Type != DataType.String)
				{
					throw new ScriptRuntimeException("'tostring' must return a string to '{0}'", funcName);
				}
				return dynValue.ToPrintString();
			}
			return this[argNum].ToPrintString();
		}

		public CallbackArguments SkipMethodCall()
		{
			if (IsMethodCall)
			{
				return new CallbackArguments(new Slice<DynValue>(m_Args, 1, m_Args.Count - 1, reversed: false), isMethodCall: false);
			}
			return this;
		}
	}
	public class Closure : RefIdObject, IScriptPrivateResource
	{
		public enum UpvaluesType
		{
			None,
			Environment,
			Closure
		}

		private static ClosureContext emptyClosure = new ClosureContext();

		public int EntryPointByteCodeLocation { get; private set; }

		public Script OwnerScript { get; private set; }

		internal ClosureContext ClosureContext { get; private set; }

		internal Closure(Script script, int idx, SymbolRef[] symbols, IEnumerable<DynValue> resolvedLocals)
		{
			OwnerScript = script;
			EntryPointByteCodeLocation = idx;
			if (symbols.Length != 0)
			{
				ClosureContext = new ClosureContext(symbols, resolvedLocals);
			}
			else
			{
				ClosureContext = emptyClosure;
			}
		}

		public DynValue Call()
		{
			return OwnerScript.Call(this);
		}

		public DynValue Call(params object[] args)
		{
			return OwnerScript.Call(this, args);
		}

		public DynValue Call(params DynValue[] args)
		{
			return OwnerScript.Call(this, args);
		}

		public ScriptFunctionDelegate GetDelegate()
		{
			return (object[] args) => Call(args).ToObject();
		}

		public ScriptFunctionDelegate<T> GetDelegate<T>()
		{
			return (object[] args) => Call(args).ToObject<T>();
		}

		public int GetUpvaluesCount()
		{
			return ClosureContext.Count;
		}

		public string GetUpvalueName(int idx)
		{
			return ClosureContext.Symbols[idx];
		}

		public DynValue GetUpvalue(int idx)
		{
			return ClosureContext[idx];
		}

		public UpvaluesType GetUpvaluesType()
		{
			switch (GetUpvaluesCount())
			{
			case 0:
				return UpvaluesType.None;
			case 1:
				if (GetUpvalueName(0) == "_ENV")
				{
					return UpvaluesType.Environment;
				}
				break;
			}
			return UpvaluesType.Closure;
		}
	}
	public sealed class CallbackFunction : RefIdObject
	{
		private static InteropAccessMode m_DefaultAccessMode = InteropAccessMode.LazyOptimized;

		public string Name { get; private set; }

		public Func<ScriptExecutionContext, CallbackArguments, DynValue> ClrCallback { get; private set; }

		public static InteropAccessMode DefaultAccessMode
		{
			get
			{
				return m_DefaultAccessMode;
			}
			set
			{
				if (value == InteropAccessMode.Default || value == InteropAccessMode.HideMembers || value == InteropAccessMode.BackgroundOptimized)
				{
					throw new ArgumentException("DefaultAccessMode");
				}
				m_DefaultAccessMode = value;
			}
		}

		public object AdditionalData { get; set; }

		public CallbackFunction(Func<ScriptExecutionContext, CallbackArguments, DynValue> callBack, string name = null)
		{
			ClrCallback = callBack;
			Name = name;
		}

		public DynValue Invoke(ScriptExecutionContext executionContext, IList<DynValue> args, bool isMethodCall = false)
		{
			if (isMethodCall)
			{
				switch (executionContext.GetScript().Options.ColonOperatorClrCallbackBehaviour)
				{
				case ColonOperatorBehaviour.TreatAsColon:
					isMethodCall = false;
					break;
				case ColonOperatorBehaviour.TreatAsDotOnUserData:
					isMethodCall = args.Count > 0 && args[0].Type == DataType.UserData;
					break;
				}
			}
			return ClrCallback(executionContext, new CallbackArguments(args, isMethodCall));
		}

		public static CallbackFunction FromDelegate(Script script, Delegate del, InteropAccessMode accessMode = InteropAccessMode.Default)
		{
			if (accessMode == InteropAccessMode.Default)
			{
				accessMode = m_DefaultAccessMode;
			}
			return new MethodMemberDescriptor(del.Method, accessMode).GetCallbackFunction(script, del.Target);
		}

		public static CallbackFunction FromMethodInfo(Script script, MethodInfo mi, object obj = null, InteropAccessMode accessMode = InteropAccessMode.Default)
		{
			if (accessMode == InteropAccessMode.Default)
			{
				accessMode = m_DefaultAccessMode;
			}
			return new MethodMemberDescriptor(mi, accessMode).GetCallbackFunction(script, obj);
		}

		public static bool CheckCallbackSignature(MethodInfo mi, bool requirePublicVisibility)
		{
			ParameterInfo[] parameters = mi.GetParameters();
			if (parameters.Length == 2 && parameters[0].ParameterType == typeof(ScriptExecutionContext) && parameters[1].ParameterType == typeof(CallbackArguments) && mi.ReturnType == typeof(DynValue))
			{
				if (!requirePublicVisibility)
				{
					return mi.IsPublic;
				}
				return true;
			}
			return false;
		}
	}
	public sealed class DynValue
	{
		private static int s_RefIDCounter;

		private int m_RefID = ++s_RefIDCounter;

		private int m_HashCode = -1;

		private bool m_ReadOnly;

		private double m_Number;

		private object m_Object;

		private DataType m_Type;

		public int ReferenceID => m_RefID;

		public DataType Type => m_Type;

		public Closure Function => m_Object as Closure;

		public double Number => m_Number;

		public DynValue[] Tuple => m_Object as DynValue[];

		public Coroutine Coroutine => m_Object as Coroutine;

		public Table Table => m_Object as Table;

		public bool Boolean => Number != 0.0;

		public string String => m_Object as string;

		public CallbackFunction Callback => m_Object as CallbackFunction;

		public TailCallData TailCallData => m_Object as TailCallData;

		public YieldRequest YieldRequest => m_Object as YieldRequest;

		public UserData UserData => m_Object as UserData;

		public bool ReadOnly => m_ReadOnly;

		public static DynValue Void { get; private set; }

		public static DynValue Nil { get; private set; }

		public static DynValue True { get; private set; }

		public static DynValue False { get; private set; }

		public static DynValue NewNil()
		{
			return new DynValue();
		}

		public static DynValue NewBoolean(bool v)
		{
			return new DynValue
			{
				m_Number = (v ? 1 : 0),
				m_Type = DataType.Boolean
			};
		}

		public static DynValue NewNumber(double num)
		{
			return new DynValue
			{
				m_Number = num,
				m_Type = DataType.Number,
				m_HashCode = -1
			};
		}

		public static DynValue NewString(string str)
		{
			return new DynValue
			{
				m_Object = str,
				m_Type = DataType.String
			};
		}

		public static DynValue NewString(StringBuilder sb)
		{
			return new DynValue
			{
				m_Object = sb.ToString(),
				m_Type = DataType.String
			};
		}

		public static DynValue NewString(string format, params object[] args)
		{
			return new DynValue
			{
				m_Object = string.Format(format, args),
				m_Type = DataType.String
			};
		}

		public static DynValue NewCoroutine(Coroutine coroutine)
		{
			return new DynValue
			{
				m_Object = coroutine,
				m_Type = DataType.Thread
			};
		}

		public static DynValue NewClosure(Closure function)
		{
			return new DynValue
			{
				m_Object = function,
				m_Type = DataType.Function
			};
		}

		public static DynValue NewCallback(Func<ScriptExecutionContext, CallbackArguments, DynValue> callBack, string name = null)
		{
			return new DynValue
			{
				m_Object = new CallbackFunction(callBack, name),
				m_Type = DataType.ClrFunction
			};
		}

		public static DynValue NewCallback(CallbackFunction function)
		{
			return new DynValue
			{
				m_Object = function,
				m_Type = DataType.ClrFunction
			};
		}

		public static DynValue NewTable(Table table)
		{
			return new DynValue
			{
				m_Object = table,
				m_Type = DataType.Table
			};
		}

		public static DynValue NewPrimeTable()
		{
			return NewTable(new Table(null));
		}

		public static DynValue NewTable(Script script)
		{
			return NewTable(new Table(script));
		}

		public static DynValue NewTable(Script script, params DynValue[] arrayValues)
		{
			return NewTable(new Table(script, arrayValues));
		}

		public static DynValue NewTailCallReq(DynValue tailFn, params DynValue[] args)
		{
			return new DynValue
			{
				m_Object = new TailCallData
				{
					Args = args,
					Function = tailFn
				},
				m_Type = DataType.TailCallRequest
			};
		}

		public static DynValue NewTailCallReq(TailCallData tailCallData)
		{
			return new DynValue
			{
				m_Object = tailCallData,
				m_Type = DataType.TailCallRequest
			};
		}

		public static DynValue NewYieldReq(DynValue[] args)
		{
			return new DynValue
			{
				m_Object = new YieldRequest
				{
					ReturnValues = args
				},
				m_Type = DataType.YieldRequest
			};
		}

		internal static DynValue NewForcedYieldReq()
		{
			return new DynValue
			{
				m_Object = new YieldRequest
				{
					Forced = true
				},
				m_Type = DataType.YieldRequest
			};
		}

		public static DynValue NewTuple(params DynValue[] values)
		{
			if (values.Length == 0)
			{
				return NewNil();
			}
			if (values.Length == 1)
			{
				return values[0];
			}
			return new DynValue
			{
				m_Object = values,
				m_Type = DataType.Tuple
			};
		}

		public static DynValue NewTupleNested(params DynValue[] values)
		{
			if (!values.Any((DynValue v) => v.Type == DataType.Tuple))
			{
				return NewTuple(values);
			}
			if (values.Length == 1)
			{
				return values[0];
			}
			List<DynValue> list = new List<DynValue>();
			foreach (DynValue dynValue in values)
			{
				if (dynValue.Type == DataType.Tuple)
				{
					list.AddRange(dynValue.Tuple);
				}
				else
				{
					list.Add(dynValue);
				}
			}
			return new DynValue
			{
				m_Object = list.ToArray(),
				m_Type = DataType.Tuple
			};
		}

		public static DynValue NewUserData(UserData userData)
		{
			return new DynValue
			{
				m_Object = userData,
				m_Type = DataType.UserData
			};
		}

		public DynValue AsReadOnly()
		{
			if (ReadOnly)
			{
				return this;
			}
			return Clone(readOnly: true);
		}

		public DynValue Clone()
		{
			return Clone(ReadOnly);
		}

		public DynValue Clone(bool readOnly)
		{
			return new DynValue
			{
				m_Object = m_Object,
				m_Number = m_Number,
				m_HashCode = m_HashCode,
				m_Type = m_Type,
				m_ReadOnly = readOnly
			};
		}

		public DynValue CloneAsWritable()
		{
			return Clone(readOnly: false);
		}

		static DynValue()
		{
			Nil = new DynValue
			{
				m_Type = DataType.Nil
			}.AsReadOnly();
			Void = new DynValue
			{
				m_Type = DataType.Void
			}.AsReadOnly();
			True = NewBoolean(v: true).AsReadOnly();
			False = NewBoolean(v: false).AsReadOnly();
		}

		public string ToPrintString()
		{
			if (m_Object != null && m_Object is RefIdObject)
			{
				RefIdObject refIdObject = (RefIdObject)m_Object;
				string typeString = Type.ToLuaTypeString();
				if (m_Object is UserData)
				{
					UserData userData = (UserData)m_Object;
					string text = userData.Descriptor.AsString(userData.Object);
					if (text != null)
					{
						return text;
					}
				}
				return refIdObject.FormatTypeString(typeString);
			}
			return Type switch
			{
				DataType.String => String, 
				DataType.Tuple => string.Join("\t", Tuple.Select((DynValue t) => t.ToPrintString()).ToArray()), 
				DataType.TailCallRequest => "(TailCallRequest -- INTERNAL!)", 
				DataType.YieldRequest => "(YieldRequest -- INTERNAL!)", 
				_ => ToString(), 
			};
		}

		public string ToDebugPrintString()
		{
			if (m_Object != null && m_Object is RefIdObject)
			{
				RefIdObject refIdObject = (RefIdObject)m_Object;
				string typeString = Type.ToLuaTypeString();
				if (m_Object is UserData)
				{
					UserData userData = (UserData)m_Object;
					string text = userData.Descriptor.AsString(userData.Object);
					if (text != null)
					{
						return text;
					}
				}
				return refIdObject.FormatTypeString(typeString);
			}
			return Type switch
			{
				DataType.Tuple => string.Join("\t", Tuple.Select((DynValue t) => t.ToPrintString()).ToArray()), 
				DataType.TailCallRequest => "(TailCallRequest)", 
				DataType.YieldRequest => "(YieldRequest)", 
				_ => ToString(), 
			};
		}

		public override string ToString()
		{
			return Type switch
			{
				DataType.Void => "void", 
				DataType.Nil => "nil", 
				DataType.Boolean => Boolean.ToString().ToLower(), 
				DataType.Number => Number.ToString(CultureInfo.InvariantCulture), 
				DataType.String => "\"" + String + "\"", 
				DataType.Function => $"(Function {Function.EntryPointByteCodeLocation:X8})", 
				DataType.ClrFunction => string.Format("(Function CLR)", Function), 
				DataType.Table => "(Table)", 
				DataType.Tuple => string.Join(", ", Tuple.Select((DynValue t) => t.ToString()).ToArray()), 
				DataType.TailCallRequest => "Tail:(" + string.Join(", ", Tuple.Select((DynValue t) => t.ToString()).ToArray()) + ")", 
				DataType.UserData => "(UserData)", 
				DataType.Thread => $"(Coroutine {Coroutine.ReferenceID:X8})", 
				_ => "(???)", 
			};
		}

		public override int GetHashCode()
		{
			if (m_HashCode != -1)
			{
				return m_HashCode;
			}
			int num = (int)Type << 27;
			switch (Type)
			{
			case DataType.Nil:
			case DataType.Void:
				m_HashCode = 0;
				break;
			case DataType.Boolean:
				m_HashCode = (Boolean ? 1 : 2);
				break;
			case DataType.Number:
				m_HashCode = num ^ Number.GetHashCode();
				break;
			case DataType.String:
				m_HashCode = num ^ String.GetHashCode();
				break;
			case DataType.Function:
				m_HashCode = num ^ Function.GetHashCode();
				break;
			case DataType.ClrFunction:
				m_HashCode = num ^ Callback.GetHashCode();
				break;
			case DataType.Table:
				m_HashCode = num ^ Table.GetHashCode();
				break;
			case DataType.Tuple:
			case DataType.TailCallRequest:
				m_HashCode = num ^ Tuple.GetHashCode();
				break;
			default:
				m_HashCode = 999;
				break;
			}
			return m_HashCode;
		}

		public override bool Equals(object obj)
		{
			if (!(obj is DynValue dynValue))
			{
				return false;
			}
			if ((dynValue.Type == DataType.Nil && Type == DataType.Void) || (dynValue.Type == DataType.Void && Type == DataType.Nil))
			{
				return true;
			}
			if (dynValue.Type != Type)
			{
				return false;
			}
			switch (Type)
			{
			case DataType.Nil:
			case DataType.Void:
				return true;
			case DataType.Boolean:
				return Boolean == dynValue.Boolean;
			case DataType.Number:
				return Number == dynValue.Number;
			case DataType.String:
				return String == dynValue.String;
			case DataType.Function:
				return Function == dynValue.Function;
			case DataType.ClrFunction:
				return Callback == dynValue.Callback;
			case DataType.Table:
				return Table == dynValue.Table;
			case DataType.Tuple:
			case DataType.TailCallRequest:
				return Tuple == dynValue.Tuple;
			case DataType.Thread:
				return Coroutine == dynValue.Coroutine;
			case DataType.UserData:
			{
				UserData userData = UserData;
				UserData userData2 = dynValue.UserData;
				if (userData == null || userData2 == null)
				{
					return false;
				}
				if (userData.Descriptor != userData2.Descriptor)
				{
					return false;
				}
				if (userData.Object == null && userData2.Object == null)
				{
					return true;
				}
				if (userData.Object != null && userData2.Object != null)
				{
					return userData.Object.Equals(userData2.Object);
				}
				return false;
			}
			default:
				return this == dynValue;
			}
		}

		public string CastToString()
		{
			DynValue dynValue = ToScalar();
			if (dynValue.Type == DataType.Number)
			{
				return dynValue.Number.ToString();
			}
			if (dynValue.Type == DataType.String)
			{
				return dynValue.String;
			}
			return null;
		}

		public double? CastToNumber()
		{
			DynValue dynValue = ToScalar();
			if (dynValue.Type == DataType.Number)
			{
				return dynValue.Number;
			}
			if (dynValue.Type == DataType.String && double.TryParse(dynValue.String, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
			{
				return result;
			}
			return null;
		}

		public bool CastToBool()
		{
			DynValue dynValue = ToScalar();
			if (dynValue.Type == DataType.Boolean)
			{
				return dynValue.Boolean;
			}
			if (dynValue.Type != 0)
			{
				return dynValue.Type != DataType.Void;
			}
			return false;
		}

		public IScriptPrivateResource GetAsPrivateResource()
		{
			return m_Object as IScriptPrivateResource;
		}

		public DynValue ToScalar()
		{
			if (Type != DataType.Tuple)
			{
				return this;
			}
			if (Tuple.Length == 0)
			{
				return Void;
			}
			return Tuple[0].ToScalar();
		}

		public void Assign(DynValue value)
		{
			if (ReadOnly)
			{
				throw new ScriptRuntimeException("Assigning on r-value");
			}
			m_Number = value.m_Number;
			m_Object = value.m_Object;
			m_Type = value.Type;
			m_HashCode = -1;
		}

		public DynValue GetLength()
		{
			if (Type == DataType.Table)
			{
				return NewNumber(Table.Length);
			}
			if (Type == DataType.String)
			{
				return NewNumber(String.Length);
			}
			throw new ScriptRuntimeException("Can't get length of type {0}", Type);
		}

		public bool IsNil()
		{
			if (Type != 0)
			{
				return Type == DataType.Void;
			}
			return true;
		}

		public bool IsNotNil()
		{
			if (Type != 0)
			{
				return Type != DataType.Void;
			}
			return false;
		}

		public bool IsVoid()
		{
			return Type == DataType.Void;
		}

		public bool IsNotVoid()
		{
			return Type != DataType.Void;
		}

		public bool IsNilOrNan()
		{
			if (Type != 0 && Type != DataType.Void)
			{
				if (Type == DataType.Number)
				{
					return double.IsNaN(Number);
				}
				return false;
			}
			return true;
		}

		internal void AssignNumber(double num)
		{
			if (ReadOnly)
			{
				throw new InternalErrorException(null, "Writing on r-value");
			}
			if (Type != DataType.Number)
			{
				throw new InternalErrorException("Can't assign number to type {0}", Type);
			}
			m_Number = num;
		}

		public static DynValue FromObject(Script script, object obj)
		{
			return ClrToScriptConversions.ObjectToDynValue(script, obj);
		}

		public object ToObject()
		{
			return ScriptToClrConversions.DynValueToObject(this);
		}

		public object ToObject(Type desiredType)
		{
			return ScriptToClrConversions.DynValueToObjectOfType(this, desiredType, null, isOptional: false);
		}

		public T ToObject<T>()
		{
			return (T)ToObject(typeof(T));
		}

		public dynamic ToDynamic()
		{
			return ScriptToClrConversions.DynValueToObject(this);
		}

		public DynValue CheckType(string funcName, DataType desiredType, int argNum = -1, TypeValidationFlags flags = TypeValidationFlags.AutoConvert)
		{
			if (Type == desiredType)
			{
				return this;
			}
			bool flag = (flags & TypeValidationFlags.AllowNil) != 0;
			if (flag && IsNil())
			{
				return this;
			}
			if ((flags & TypeValidationFlags.AutoConvert) != 0)
			{
				switch (desiredType)
				{
				case DataType.Boolean:
					return NewBoolean(CastToBool());
				case DataType.Number:
				{
					double? num = CastToNumber();
					if (num.HasValue)
					{
						return NewNumber(num.Value);
					}
					break;
				}
				}
				if (desiredType == DataType.String)
				{
					string text = CastToString();
					if (text != null)
					{
						return NewString(text);
					}
				}
			}
			if (IsVoid())
			{
				throw ScriptRuntimeException.BadArgumentNoValue(argNum, funcName, desiredType);
			}
			throw ScriptRuntimeException.BadArgument(argNum, funcName, desiredType, Type, flag);
		}

		public T CheckUserDataType<T>(string funcName, int argNum = -1, TypeValidationFlags flags = TypeValidationFlags.AutoConvert)
		{
			DynValue dynValue = CheckType(funcName, DataType.UserData, argNum, flags);
			bool allowNil = (flags & TypeValidationFlags.AllowNil) != 0;
			if (dynValue.IsNil())
			{
				return default(T);
			}
			object @object = dynValue.UserData.Object;
			if (@object != null && @object is T)
			{
				return (T)@object;
			}
			throw ScriptRuntimeException.BadArgumentUserData(argNum, funcName, typeof(T), @object, allowNil);
		}
	}
	public struct TablePair
	{
		private static TablePair s_NilNode = new TablePair(DynValue.Nil, DynValue.Nil);

		private DynValue key;

		private DynValue value;

		public DynValue Key
		{
			get
			{
				return key;
			}
			private set
			{
				Key = key;
			}
		}

		public DynValue Value
		{
			get
			{
				return value;
			}
			set
			{
				if (key.IsNotNil())
				{
					Value = value;
				}
			}
		}

		public static TablePair Nil => s_NilNode;

		public TablePair(DynValue key, DynValue val)
		{
			this.key = key;
			value = val;
		}
	}
	public class ScriptExecutionContext : IScriptPrivateResource
	{
		private Processor m_Processor;

		private CallbackFunction m_Callback;

		public bool IsDynamicExecution { get; private set; }

		public SourceRef CallingLocation { get; private set; }

		public object AdditionalData
		{
			get
			{
				if (m_Callback == null)
				{
					return null;
				}
				return m_Callback.AdditionalData;
			}
			set
			{
				if (m_Callback == null)
				{
					throw new InvalidOperationException("Cannot set additional data on a context which has no callback");
				}
				m_Callback.AdditionalData = value;
			}
		}

		public Table CurrentGlobalEnv
		{
			get
			{
				DynValue dynValue = EvaluateSymbolByName("_ENV");
				if (dynValue == null || dynValue.Type != DataType.Table)
				{
					return null;
				}
				return dynValue.Table;
			}
		}

		public Script OwnerScript => GetScript();

		internal ScriptExecutionContext(Processor p, CallbackFunction callBackFunction, SourceRef sourceRef, bool isDynamic = false)
		{
			IsDynamicExecution = isDynamic;
			m_Processor = p;
			m_Callback = callBackFunction;
			CallingLocation = sourceRef;
		}

		public Table GetMetatable(DynValue value)
		{
			return m_Processor.GetMetatable(value);
		}

		public DynValue GetMetamethod(DynValue value, string metamethod)
		{
			return m_Processor.GetMetamethod(value, metamethod);
		}

		public DynValue GetMetamethodTailCall(DynValue value, string metamethod, params DynValue[] args)
		{
			DynValue metamethod2 = GetMetamethod(value, metamethod);
			if (metamethod2 == null)
			{
				return null;
			}
			return DynValue.NewTailCallReq(metamethod2, args);
		}

		public DynValue GetBinaryMetamethod(DynValue op1, DynValue op2, string eventName)
		{
			return m_Processor.GetBinaryMetamethod(op1, op2, eventName);
		}

		public Script GetScript()
		{
			return m_Processor.GetScript();
		}

		public Coroutine GetCallingCoroutine()
		{
			return m_Processor.AssociatedCoroutine;
		}

		public DynValue EmulateClassicCall(CallbackArguments args, string functionName, Func<LuaState, int> callback)
		{
			LuaState luaState = new LuaState(this, args, functionName);
			int retvals = callback(luaState);
			return luaState.GetReturnValue(retvals);
		}

		public DynValue Call(DynValue func, params DynValue[] args)
		{
			if (func.Type == DataType.Function)
			{
				return GetScript().Call(func, args);
			}
			if (func.Type == DataType.ClrFunction)
			{
				DynValue dynValue;
				while (true)
				{
					dynValue = func.Callback.Invoke(this, args);
					if (dynValue.Type == DataType.YieldRequest)
					{
						throw ScriptRuntimeException.CannotYield();
					}
					if (dynValue.Type != DataType.TailCallRequest)
					{
						break;
					}
					TailCallData tailCallData = dynValue.TailCallData;
					if (tailCallData.Continuation != null || tailCallData.ErrorHandler != null)
					{
						throw new ScriptRuntimeException("the function passed cannot be called directly. wrap in a script function instead.");
					}
					args = tailCallData.Args;
					func = tailCallData.Function;
				}
				return dynValue;
			}
			int num = 10;
			while (num > 0)
			{
				DynValue metamethod = GetMetamethod(func, "__call");
				if (metamethod == null && metamethod.IsNil())
				{
					throw ScriptRuntimeException.AttemptToCallNonFunc(func.Type);
				}
				func = metamethod;
				if (func.Type == DataType.Function || func.Type == DataType.ClrFunction)
				{
					return Call(func, args);
				}
			}
			throw ScriptRuntimeException.LoopInCall();
		}

		public DynValue EvaluateSymbol(SymbolRef symref)
		{
			if (symref == null)
			{
				return DynValue.Nil;
			}
			return m_Processor.GetGenericSymbol(symref);
		}

		public DynValue EvaluateSymbolByName(string symbol)
		{
			return EvaluateSymbol(FindSymbolByName(symbol));
		}

		public SymbolRef FindSymbolByName(string symbol)
		{
			return m_Processor.FindSymbolByName(symbol);
		}

		public void PerformMessageDecorationBeforeUnwind(DynValue messageHandler, ScriptRuntimeException exception)
		{
			if (messageHandler != null)
			{
				exception.DecoratedMessage = m_Processor.PerformMessageDecorationBeforeUnwind(messageHandler, exception.Message, CallingLocation);
			}
			else
			{
				exception.DecoratedMessage = exception.Message;
			}
		}
	}
	public enum CoroutineState
	{
		Main,
		NotStarted,
		Suspended,
		ForceSuspended,
		Running,
		Dead
	}
	public static class LinqHelpers
	{
		public static IEnumerable<T> Convert<T>(this IEnumerable<DynValue> enumerable, DataType type)
		{
			return from v in enumerable
				where v.Type == type
				select v.ToObject<T>();
		}

		public static IEnumerable<DynValue> OfDataType(this IEnumerable<DynValue> enumerable, DataType type)
		{
			return enumerable.Where((DynValue v) => v.Type == type);
		}

		public static IEnumerable<object> AsObjects(this IEnumerable<DynValue> enumerable)
		{
			return enumerable.Select((DynValue v) => v.ToObject());
		}

		public static IEnumerable<T> AsObjects<T>(this IEnumerable<DynValue> enumerable)
		{
			return enumerable.Select((DynValue v) => v.ToObject<T>());
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
	public sealed class MoonSharpUserDataAttribute : Attribute
	{
		public InteropAccessMode AccessMode { get; set; }

		public MoonSharpUserDataAttribute()
		{
			AccessMode = InteropAccessMode.Default;
		}
	}
	internal class AutoDescribingUserDataDescriptor : IUserDataDescriptor
	{
		private string m_FriendlyName;

		private Type m_Type;

		public string Name => m_FriendlyName;

		public Type Type => m_Type;

		public AutoDescribingUserDataDescriptor(Type type, string friendlyName)
		{
			m_FriendlyName = friendlyName;
			m_Type = type;
		}

		public DynValue Index(Script script, object obj, DynValue index, bool isDirectIndexing)
		{
			if (obj is IUserDataType userDataType)
			{
				return userDataType.Index(script, index, isDirectIndexing);
			}
			return null;
		}

		public bool SetIndex(Script script, object obj, DynValue index, DynValue value, bool isDirectIndexing)
		{
			if (obj is IUserDataType userDataType)
			{
				return userDataType.SetIndex(script, index, value, isDirectIndexing);
			}
			return false;
		}

		public string AsString(object obj)
		{
			return obj?.ToString();
		}

		public DynValue MetaIndex(Script script, object obj, string metaname)
		{
			if (obj is IUserDataType userDataType)
			{
				return userDataType.MetaIndex(script, metaname);
			}
			return null;
		}

		public bool IsTypeCompatible(Type type, object obj)
		{
			return Framework.Do.IsInstanceOfType(type, obj);
		}
	}
	public enum InteropAccessMode
	{
		Reflection,
		LazyOptimized,
		Preoptimized,
		BackgroundOptimized,
		Hardwired,
		HideMembers,
		NoReflectionAllowed,
		Default
	}
	public enum SymbolRefType
	{
		Local,
		Upvalue,
		Global,
		DefaultEnv
	}
	public class SymbolRef
	{
		private static SymbolRef s_DefaultEnv = new SymbolRef
		{
			i_Type = SymbolRefType.DefaultEnv
		};

		internal SymbolRefType i_Type;

		internal SymbolRef i_Env;

		internal int i_Index;

		internal string i_Name;

		public SymbolRefType Type => i_Type;

		public int Index => i_Index;

		public string Name => i_Name;

		public SymbolRef Environment => i_Env;

		public static SymbolRef DefaultEnv => s_DefaultEnv;

		public static SymbolRef Global(string name, SymbolRef envSymbol)
		{
			return new SymbolRef
			{
				i_Index = -1,
				i_Type = SymbolRefType.Global,
				i_Env = envSymbol,
				i_Name = name
			};
		}

		internal static SymbolRef Local(string name, int index)
		{
			return new SymbolRef
			{
				i_Index = index,
				i_Type = SymbolRefType.Local,
				i_Name = name
			};
		}

		internal static SymbolRef Upvalue(string name, int index)
		{
			return new SymbolRef
			{
				i_Index = index,
				i_Type = SymbolRefType.Upvalue,
				i_Name = name
			};
		}

		public override string ToString()
		{
			if (i_Type == SymbolRefType.DefaultEnv)
			{
				return "(default _ENV)";
			}
			if (i_Type == SymbolRefType.Global)
			{
				return string.Format("{2} : {0} / {1}", i_Type, i_Env, i_Name);
			}
			return string.Format("{2} : {0}[{1}]", i_Type, i_Index, i_Name);
		}

		internal void WriteBinary(BinaryWriter bw)
		{
			bw.Write((byte)i_Type);
			bw.Write(i_Index);
			bw.Write(i_Name);
		}

		internal static SymbolRef ReadBinary(BinaryReader br)
		{
			return new SymbolRef
			{
				i_Type = (SymbolRefType)br.ReadByte(),
				i_Index = br.ReadInt32(),
				i_Name = br.ReadString()
			};
		}

		internal void WriteBinaryEnv(BinaryWriter bw, Dictionary<SymbolRef, int> symbolMap)
		{
			if (i_Env != null)
			{
				bw.Write(symbolMap[i_Env]);
			}
			else
			{
				bw.Write(-1);
			}
		}

		internal void ReadBinaryEnv(BinaryReader br, SymbolRef[] symbolRefs)
		{
			int num = br.ReadInt32();
			if (num >= 0)
			{
				i_Env = symbolRefs[num];
			}
		}
	}
	public enum DataType
	{
		Nil,
		Void,
		Boolean,
		Number,
		String,
		Function,
		Table,
		Tuple,
		UserData,
		Thread,
		ClrFunction,
		TailCallRequest,
		YieldRequest
	}
	public static class LuaTypeExtensions
	{
		internal const DataType MaxMetaTypes = DataType.Table;

		internal const DataType MaxConvertibleTypes = DataType.ClrFunction;

		public static bool CanHaveTypeMetatables(this DataType type)
		{
			return type < DataType.Table;
		}

		public static string ToErrorTypeString(this DataType type)
		{
			return type switch
			{
				DataType.Void => "no value", 
				DataType.Nil => "nil", 
				DataType.Boolean => "boolean", 
				DataType.Number => "number", 
				DataType.String => "string", 
				DataType.Function => "function", 
				DataType.ClrFunction => "function", 
				DataType.Table => "table", 
				DataType.UserData => "userdata", 
				DataType.Thread => "coroutine", 
				_ => $"internal<{type.ToLuaDebuggerString()}>", 
			};
		}

		public static string ToLuaDebuggerString(this DataType type)
		{
			return type.ToString().ToLowerInvariant();
		}

		public static string ToLuaTypeString(this DataType type)
		{
			switch (type)
			{
			case DataType.Nil:
			case DataType.Void:
				return "nil";
			case DataType.Boolean:
				return "boolean";
			case DataType.Number:
				return "number";
			case DataType.String:
				return "string";
			case DataType.Function:
				return "function";
			case DataType.ClrFunction:
				return "function";
			case DataType.Table:
				return "table";
			case DataType.UserData:
				return "userdata";
			case DataType.Thread:
				return "thread";
			default:
				throw new ScriptRuntimeException("Unexpected LuaType {0}", type);
			}
		}
	}
	public enum ColonOperatorBehaviour
	{
		TreatAsDot,
		TreatAsDotOnUserData,
		TreatAsColon
	}
	[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
	public sealed class MoonSharpModuleConstantAttribute : Attribute
	{
		public string Name { get; set; }
	}
	internal static class NamespaceDoc
	{
	}
	public class Script : IScriptPrivateResource
	{
		public const string VERSION = "2.0.0.0";

		public const string LUA_VERSION = "5.2";

		private Processor m_MainProcessor;

		private ByteCode m_ByteCode;

		private List<SourceCode> m_Sources = new List<SourceCode>();

		private Table m_GlobalTable;

		private IDebugger m_Debugger;

		private Table[] m_TypeMetatables = new Table[6];

		public static ScriptOptions DefaultOptions { get; private set; }

		public ScriptOptions Options { get; private set; }

		public static ScriptGlobalOptions GlobalOptions { get; private set; }

		public PerformanceStatistics PerformanceStats { get; private set; }

		public Table Globals => m_GlobalTable;

		public bool DebuggerEnabled
		{
			get
			{
				return m_MainProcessor.DebuggerEnabled;
			}
			set
			{
				m_MainProcessor.DebuggerEnabled = value;
			}
		}

		public int SourceCodeCount => m_Sources.Count;

		public Table Registry { get; private set; }

		Script IScriptPrivateResource.OwnerScript => this;

		static Script()
		{
			GlobalOptions = new ScriptGlobalOptions();
			DefaultOptions = new ScriptOptions
			{
				DebugPrint = delegate(string s)
				{
					GlobalOptions.Platform.DefaultPrint(s);
				},
				DebugInput = (string s) => GlobalOptions.Platform.DefaultInput(s),
				CheckThreadAccess = true,
				ScriptLoader = PlatformAutoDetector.GetDefaultScriptLoader(),
				TailCallOptimizationThreshold = 65536
			};
		}

		public Script()
			: this(CoreModules.Preset_Default)
		{
		}

		public Script(CoreModules coreModules)
		{
			Options = new ScriptOptions(DefaultOptions);
			PerformanceStats = new PerformanceStatistics();
			Registry = new Table(this);
			m_ByteCode = new ByteCode(this);
			m_MainProcessor = new Processor(this, m_GlobalTable, m_ByteCode);
			m_GlobalTable = new Table(this).RegisterCoreModules(coreModules);
		}

		public DynValue LoadFunction(string code, Table globalTable = null, string funcFriendlyName = null)
		{
			this.CheckScriptOwnership(globalTable);
			SourceCode sourceCode = new SourceCode($"libfunc_{funcFriendlyName ?? m_Sources.Count.ToString()}", code, m_Sources.Count, this);
			m_Sources.Add(sourceCode);
			int address = Loader_Fast.LoadFunction(this, sourceCode, m_ByteCode, globalTable != null || m_GlobalTable != null);
			SignalSourceCodeChange(sourceCode);
			SignalByteCodeChange();
			return MakeClosure(address, globalTable ?? m_GlobalTable);
		}

		private void SignalByteCodeChange()
		{
			if (m_Debugger != null)
			{
				m_Debugger.SetByteCode(m_ByteCode.Code.Select((Instruction s) => s.ToString()).ToArray());
			}
		}

		private void SignalSourceCodeChange(SourceCode source)
		{
			if (m_Debugger != null)
			{
				m_Debugger.SetSourceCode(source);
			}
		}

		public DynValue LoadString(string code, Table globalTable = null, string codeFriendlyName = null)
		{
			this.CheckScriptOwnership(globalTable);
			if (code.StartsWith("MoonSharp_dump_b64::"))
			{
				code = code.Substring("MoonSharp_dump_b64::".Length);
				using MemoryStream stream = new MemoryStream(Convert.FromBase64String(code));
				return LoadStream(stream, globalTable, codeFriendlyName);
			}
			string text = string.Format("{0}", codeFriendlyName ?? ("chunk_" + m_Sources.Count));
			SourceCode sourceCode = new SourceCode(codeFriendlyName ?? text, code, m_Sources.Count, this);
			m_Sources.Add(sourceCode);
			int address = Loader_Fast.LoadChunk(this, sourceCode, m_ByteCode);
			SignalSourceCodeChange(sourceCode);
			SignalByteCodeChange();
			return MakeClosure(address, globalTable ?? m_GlobalTable);
		}

		public DynValue LoadStream(Stream stream, Table globalTable = null, string codeFriendlyName = null)
		{
			this.CheckScriptOwnership(globalTable);
			Stream stream2 = new UndisposableStream(stream);
			if (!Processor.IsDumpStream(stream2))
			{
				using (StreamReader streamReader = new StreamReader(stream2))
				{
					string code = streamReader.ReadToEnd();
					return LoadString(code, globalTable, codeFriendlyName);
				}
			}
			string text = string.Format("{0}", codeFriendlyName ?? ("dump_" + m_Sources.Count));
			SourceCode sourceCode = new SourceCode(codeFriendlyName ?? text, $"-- This script was decoded from a binary dump - dump_{m_Sources.Count}", m_Sources.Count, this);
			m_Sources.Add(sourceCode);
			bool hasUpvalues;
			int address = m_MainProcessor.Undump(stream2, m_Sources.Count - 1, globalTable ?? m_GlobalTable, out hasUpvalues);
			SignalSourceCodeChange(sourceCode);
			SignalByteCodeChange();
			if (hasUpvalues)
			{
				return MakeClosure(address, globalTable ?? m_GlobalTable);
			}
			return MakeClosure(address);
		}

		public void Dump(DynValue function, Stream stream)
		{
			this.CheckScriptOwnership(function);
			if (function.Type != DataType.Function)
			{
				throw new ArgumentException("function arg is not a function!");
			}
			if (!stream.CanWrite)
			{
				throw new ArgumentException("stream is readonly!");
			}
			Closure.UpvaluesType upvaluesType = function.Function.GetUpvaluesType();
			if (upvaluesType == Closure.UpvaluesType.Closure)
			{
				throw new ArgumentException("function arg has upvalues other than _ENV");
			}
			UndisposableStream stream2 = new UndisposableStream(stream);
			m_MainProcessor.Dump(stream2, function.Function.EntryPointByteCodeLocation, upvaluesType == Closure.UpvaluesType.Environment);
		}

		public DynValue LoadFile(string filename, Table globalContext = null, string friendlyFilename = null)
		{
			this.CheckScriptOwnership(globalContext);
			filename = Options.ScriptLoader.ResolveFileName(filename, globalContext ?? m_GlobalTable);
			object obj = Options.ScriptLoader.LoadFile(filename, globalContext ?? m_GlobalTable);
			if (obj is string)
			{
				return LoadString((string)obj, globalContext, friendlyFilename ?? filename);
			}
			if (obj is byte[])
			{
				using (MemoryStream stream = new MemoryStream((byte[])obj))
				{
					return LoadStream(stream, globalContext, friendlyFilename ?? filename);
				}
			}
			if (obj is Stream)
			{
				try
				{
					return LoadStream((Stream)obj, globalContext, friendlyFilename ?? filename);
				}
				finally
				{
					((Stream)obj).Dispose();
				}
			}
			if (obj == null)
			{
				throw new InvalidCastException("Unexpected null from IScriptLoader.LoadFile");
			}
			throw new InvalidCastException($"Unsupported return type from IScriptLoader.LoadFile : {obj.GetType()}");
		}

		public DynValue DoString(string code, Table globalContext = null, string codeFriendlyName = null)
		{
			DynValue function = LoadString(code, globalContext, codeFriendlyName);
			return Call(function);
		}

		public DynValue DoStream(Stream stream, Table globalContext = null, string codeFriendlyName = null)
		{
			DynValue function = LoadStream(stream, globalContext, codeFriendlyName);
			return Call(function);
		}

		public DynValue DoFile(string filename, Table globalContext = null, string codeFriendlyName = null)
		{
			DynValue function = LoadFile(filename, globalContext, codeFriendlyName);
			return Call(function);
		}

		public static DynValue RunFile(string filename)
		{
			return new Script().DoFile(filename);
		}

		public static DynValue RunString(string code)
		{
			return new Script().DoString(code);
		}

		private DynValue MakeClosure(int address, Table envTable = null)
		{
			this.CheckScriptOwnership(envTable);
			Closure function;
			if (envTable == null)
			{
				Instruction instruction = m_MainProcessor.FindMeta(ref address);
				function = ((instruction == null || instruction.NumVal2 != 0) ? new Closure(this, address, new SymbolRef[0], new DynValue[0]) : new Closure(this, address, new SymbolRef[1] { SymbolRef.Upvalue("_ENV", 0) }, new DynValue[1] { instruction.Value }));
			}
			else
			{
				SymbolRef[] symbols = new SymbolRef[1]
				{
					new SymbolRef
					{
						i_Env = null,
						i_Index = 0,
						i_Name = "_ENV",
						i_Type = SymbolRefType.DefaultEnv
					}
				};
				DynValue[] resolvedLocals = new DynValue[1] { DynValue.NewTable(envTable) };
				function = new Closure(this, address, symbols, resolvedLocals);
			}
			return DynValue.NewClosure(function);
		}

		public DynValue Call(DynValue function)
		{
			return Call(function, new DynValue[0]);
		}

		public DynValue Call(DynValue function, params DynValue[] args)
		{
			this.CheckScriptOwnership(function);
			this.CheckScriptOwnership(args);
			if (function.Type != DataType.Function && function.Type != DataType.ClrFunction)
			{
				DynValue metamethod = m_MainProcessor.GetMetamethod(function, "__call");
				if (metamethod == null)
				{
					throw new ArgumentException("function is not a function and has no __call metamethod.");
				}
				DynValue[] array = new DynValue[args.Length + 1];
				array[0] = function;
				for (int i = 0; i < args.Length; i++)
				{
					array[i + 1] = args[i];
				}
				function = metamethod;
				args = array;
			}
			else if (function.Type == DataType.ClrFunction)
			{
				return function.Callback.ClrCallback(CreateDynamicExecutionContext(function.Callback), new CallbackArguments(args, isMethodCall: false));
			}
			return m_MainProcessor.Call(function, args);
		}

		public DynValue Call(DynValue function, params object[] args)
		{
			DynValue[] array = new DynValue[args.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = DynValue.FromObject(this, args[i]);
			}
			return Call(function, array);
		}

		public DynValue Call(object function)
		{
			return Call(DynValue.FromObject(this, function));
		}

		public DynValue Call(object function, params object[] args)
		{
			return Call(DynValue.FromObject(this, function), args);
		}

		public DynValue CreateCoroutine(DynValue function)
		{
			this.CheckScriptOwnership(function);
			if (function.Type == DataType.Function)
			{
				return m_MainProcessor.Coroutine_Create(function.Function);
			}
			if (function.Type == DataType.ClrFunction)
			{
				return DynValue.NewCoroutine(new Coroutine(function.Callback));
			}
			throw new ArgumentException("function is not of DataType.Function or DataType.ClrFunction");
		}

		public DynValue CreateCoroutine(object function)
		{
			return CreateCoroutine(DynValue.FromObject(this, function));
		}

		public void AttachDebugger(IDebugger debugger)
		{
			DebuggerEnabled = true;
			m_Debugger = debugger;
			m_MainProcessor.AttachDebugger(debugger);
			foreach (SourceCode source in m_Sources)
			{
				SignalSourceCodeChange(source);
			}
			SignalByteCodeChange();
		}

		public SourceCode GetSourceCode(int sourceCodeID)
		{
			return m_Sources[sourceCodeID];
		}

		public DynValue RequireModule(string modname, Table globalContext = null)
		{
			this.CheckScriptOwnership(globalContext);
			Table globalContext2 = globalContext ?? m_GlobalTable;
			string text = Options.ScriptLoader.ResolveModuleName(modname, globalContext2);
			if (text == null)
			{
				throw new ScriptRuntimeException("module '{0}' not found", modname);
			}
			return LoadFile(text, globalContext, text);
		}

		public Table GetTypeMetatable(DataType type)
		{
			if (type >= DataType.Nil && (int)type < m_TypeMetatables.Length)
			{
				return m_TypeMetatables[(int)type];
			}
			return null;
		}

		public void SetTypeMetatable(DataType type, Table metatable)
		{
			this.CheckScriptOwnership(metatable);
			int num = (int)type;
			if (num >= 0 && num < m_TypeMetatables.Length)
			{
				m_TypeMetatables[num] = metatable;
				return;
			}
			throw new ArgumentException("Specified type not supported : " + type);
		}

		public static void WarmUp()
		{
			new Script(CoreModules.Basic).LoadString("return 1;");
		}

		public DynamicExpression CreateDynamicExpression(string code)
		{
			DynamicExprExpression expr = Loader_Fast.LoadDynamicExpr(this, new SourceCode("__dynamic", code, -1, this));
			return new DynamicExpression(this, code, expr);
		}

		public DynamicExpression CreateConstantDynamicExpression(string code, DynValue constant)
		{
			this.CheckScriptOwnership(constant);
			return new DynamicExpression(this, code, constant);
		}

		internal ScriptExecutionContext CreateDynamicExecutionContext(CallbackFunction func = null)
		{
			return new ScriptExecutionContext(m_MainProcessor, func, null, isDynamic: true);
		}

		public static string GetBanner(string subproduct = null)
		{
			subproduct = ((subproduct != null) ? (subproduct + " ") : "");
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine(string.Format("MoonSharp {0}{1} [{2}]", subproduct, "2.0.0.0", GlobalOptions.Platform.GetPlatformName()));
			stringBuilder.AppendLine("Copyright (C) 2014-2016 Marco Mastropaolo");
			stringBuilder.AppendLine("http://www.moonsharp.org");
			return stringBuilder.ToString();
		}
	}
	public class Table : RefIdObject, IScriptPrivateResource
	{
		private readonly LinkedList<TablePair> m_Values;

		private readonly LinkedListIndex<DynValue, TablePair> m_ValueMap;

		private readonly LinkedListIndex<string, TablePair> m_StringMap;

		private readonly LinkedListIndex<int, TablePair> m_ArrayMap;

		private readonly Script m_Owner;

		private int m_InitArray;

		private int m_CachedLength = -1;

		private bool m_ContainsNilEntries;

		private Table m_MetaTable;

		public Script OwnerScript => m_Owner;

		public object this[params object[] keys]
		{
			get
			{
				return Get(keys).ToObject();
			}
			set
			{
				Set(keys, DynValue.FromObject(OwnerScript, value));
			}
		}

		public object this[object key]
		{
			get
			{
				return Get(key).ToObject();
			}
			set
			{
				Set(key, DynValue.FromObject(OwnerScript, value));
			}
		}

		public int Length
		{
			get
			{
				if (m_CachedLength < 0)
				{
					m_CachedLength = 0;
					for (int i = 1; m_ArrayMap.ContainsKey(i) && !m_ArrayMap.Find(i).Value.Value.IsNil(); i++)
					{
						m_CachedLength = i;
					}
				}
				return m_CachedLength;
			}
		}

		public Table MetaTable
		{
			get
			{
				return m_MetaTable;
			}
			set
			{
				this.CheckScriptOwnership(m_MetaTable);
				m_MetaTable = value;
			}
		}

		public IEnumerable<TablePair> Pairs => m_Values.Select((TablePair n) => new TablePair(n.Key, n.Value));

		public IEnumerable<DynValue> Keys => m_Values.Select((TablePair n) => n.Key);

		public IEnumerable<DynValue> Values => m_Values.Select((TablePair n) => n.Value);

		public Table(Script owner)
		{
			m_Values = new LinkedList<TablePair>();
			m_StringMap = new LinkedListIndex<string, TablePair>(m_Values);
			m_ArrayMap = new LinkedListIndex<int, TablePair>(m_Values);
			m_ValueMap = new LinkedListIndex<DynValue, TablePair>(m_Values);
			m_Owner = owner;
		}

		public Table(Script owner, params DynValue[] arrayValues)
			: this(owner)
		{
			for (int i = 0; i < arrayValues.Length; i++)
			{
				Set(DynValue.NewNumber(i + 1), arrayValues[i]);
			}
		}

		public void Clear()
		{
			m_Values.Clear();
			m_StringMap.Clear();
			m_ArrayMap.Clear();
			m_ValueMap.Clear();
			m_CachedLength = -1;
		}

		private int GetIntegralKey(double d)
		{
			int num = (int)d;
			if (d >= 1.0 && d == (double)num)
			{
				return num;
			}
			return -1;
		}

		private Table ResolveMultipleKeys(object[] keys, out object key)
		{
			Table table = this;
			key = ((keys.Length != 0) ? keys[0] : null);
			for (int i = 1; i < keys.Length; i++)
			{
				DynValue obj = table.RawGet(key) ?? throw new ScriptRuntimeException("Key '{0}' did not point to anything");
				if (obj.Type != DataType.Table)
				{
					throw new ScriptRuntimeException("Key '{0}' did not point to a table");
				}
				table = obj.Table;
				key = keys[i];
			}
			return table;
		}

		public void Append(DynValue value)
		{
			this.CheckScriptOwnership(value);
			PerformTableSet(m_ArrayMap, Length + 1, DynValue.NewNumber(Length + 1), value, isNumber: true, Length + 1);
		}

		private void PerformTableSet<T>(LinkedListIndex<T, TablePair> listIndex, T key, DynValue keyDynValue, DynValue value, bool isNumber, int appendKey)
		{
			TablePair tablePair = listIndex.Set(key, new TablePair(keyDynValue, value));
			if (m_ContainsNilEntries && value.IsNotNil() && (tablePair.Value == null || tablePair.Value.IsNil()))
			{
				CollectDeadKeys();
			}
			else if (value.IsNil())
			{
				m_ContainsNilEntries = true;
				if (isNumber)
				{
					m_CachedLength = -1;
				}
			}
			else
			{
				if (!isNumber || (tablePair.Value != null && !tablePair.Value.IsNilOrNan()))
				{
					return;
				}
				if (appendKey >= 0)
				{
					LinkedListNode<TablePair> linkedListNode = m_ArrayMap.Find(appendKey + 1);
					if (linkedListNode == null || linkedListNode.Value.Value == null || linkedListNode.Value.Value.IsNil())
					{
						m_CachedLength++;
					}
					else
					{
						m_CachedLength = -1;
					}
				}
				else
				{
					m_CachedLength = -1;
				}
			}
		}

		public void Set(string key, DynValue value)
		{
			if (key == null)
			{
				throw ScriptRuntimeException.TableIndexIsNil();
			}
			this.CheckScriptOwnership(value);
			PerformTableSet(m_StringMap, key, DynValue.NewString(key), value, isNumber: false, -1);
		}

		public void Set(int key, DynValue value)
		{
			this.CheckScriptOwnership(value);
			PerformTableSet(m_ArrayMap, key, DynValue.NewNumber(key), value, isNumber: true, -1);
		}

		public void Set(DynValue key, DynValue value)
		{
			if (key.IsNilOrNan())
			{
				if (key.IsNil())
				{
					throw ScriptRuntimeException.TableIndexIsNil();
				}
				throw ScriptRuntimeException.TableIndexIsNaN();
			}
			if (key.Type == DataType.String)
			{
				Set(key.String, value);
				return;
			}
			if (key.Type == DataType.Number)
			{
				int integralKey = GetIntegralKey(key.Number);
				if (integralKey > 0)
				{
					Set(integralKey, value);
					return;
				}
			}
			this.CheckScriptOwnership(key);
			this.CheckScriptOwnership(value);
			PerformTableSet(m_ValueMap, key, key, value, isNumber: false, -1);
		}

		public void Set(object key, DynValue value)
		{
			if (key == null)
			{
				throw ScriptRuntimeException.TableIndexIsNil();
			}
			if (key is string)
			{
				Set((string)key, value);
			}
			else if (key is int)
			{
				Set((int)key, value);
			}
			else
			{
				Set(DynValue.FromObject(OwnerScript, key), value);
			}
		}

		public void Set(object[] keys, DynValue value)
		{
			if (keys == null || keys.Length == 0)
			{
				throw ScriptRuntimeException.TableIndexIsNil();
			}
			ResolveMultipleKeys(keys, out var key).Set(key, value);
		}

		public DynValue Get(string key)
		{
			return RawGet(key) ?? DynValue.Nil;
		}

		public DynValue Get(int key)
		{
			return RawGet(key) ?? DynValue.Nil;
		}

		public DynValue Get(DynValue key)
		{
			return RawGet(key) ?? DynValue.Nil;
		}

		public DynValue Get(object key)
		{
			return RawGet(key) ?? DynValue.Nil;
		}

		public DynValue Get(params object[] keys)
		{
			return RawGet(keys) ?? DynValue.Nil;
		}

		private static DynValue RawGetValue(LinkedListNode<TablePair> linkedListNode)
		{
			return linkedListNode?.Value.Value;
		}

		public DynValue RawGet(string key)
		{
			return RawGetValue(m_StringMap.Find(key));
		}

		public DynValue RawGet(int key)
		{
			return RawGetValue(m_ArrayMap.Find(key));
		}

		public DynValue RawGet(DynValue key)
		{
			if (key.Type == DataType.String)
			{
				return RawGet(key.String);
			}
			if (key.Type == DataType.Number)
			{
				int integralKey = GetIntegralKey(key.Number);
				if (integralKey > 0)
				{
					return RawGet(integralKey);
				}
			}
			return RawGetValue(m_ValueMap.Find(key));
		}

		public DynValue RawGet(object key)
		{
			if (key == null)
			{
				return null;
			}
			if (key is string)
			{
				return RawGet((string)key);
			}
			if (key is int)
			{
				return RawGet((int)key);
			}
			return RawGet(DynValue.FromObject(OwnerScript, key));
		}

		public DynValue RawGet(params object[] keys)
		{
			if (keys == null || keys.Length == 0)
			{
				return null;
			}
			object key;
			return ResolveMultipleKeys(keys, out key).RawGet(key);
		}

		private bool PerformTableRemove<T>(LinkedListIndex<T, TablePair> listIndex, T key, bool isNumber)
		{
			bool num = listIndex.Remove(key);
			if (num && isNumber)
			{
				m_CachedLength = -1;
			}
			return num;
		}

		public bool Remove(string key)
		{
			return PerformTableRemove(m_StringMap, key, isNumber: false);
		}

		public bool Remove(int key)
		{
			return PerformTableRemove(m_ArrayMap, key, isNumber: true);
		}

		public bool Remove(DynValue key)
		{
			if (key.Type == DataType.String)
			{
				return Remove(key.String);
			}
			if (key.Type == DataType.Number)
			{
				int integralKey = GetIntegralKey(key.Number);
				if (integralKey > 0)
				{
					return Remove(integralKey);
				}
			}
			return PerformTableRemove(m_ValueMap, key, isNumber: false);
		}

		public bool Remove(object key)
		{
			if (key is string)
			{
				return Remove((string)key);
			}
			if (key is int)
			{
				return Remove((int)key);
			}
			return Remove(DynValue.FromObject(OwnerScript, key));
		}

		public bool Remove(params object[] keys)
		{
			if (keys == null || keys.Length == 0)
			{
				return false;
			}
			object key;
			return ResolveMultipleKeys(keys, out key).Remove(key);
		}

		public void CollectDeadKeys()
		{
			for (LinkedListNode<TablePair> linkedListNode = m_Values.First; linkedListNode != null; linkedListNode = linkedListNode.Next)
			{
				if (linkedListNode.Value.Value.IsNil())
				{
					Remove(linkedListNode.Value.Key);
				}
			}
			m_ContainsNilEntries = false;
			m_CachedLength = -1;
		}

		public TablePair? NextKey(DynValue v)
		{
			if (v.IsNil())
			{
				LinkedListNode<TablePair> first = m_Values.First;
				if (first == null)
				{
					return TablePair.Nil;
				}
				if (first.Value.Value.IsNil())
				{
					return NextKey(first.Value.Key);
				}
				return first.Value;
			}
			if (v.Type == DataType.String)
			{
				return GetNextOf(m_StringMap.Find(v.String));
			}
			if (v.Type == DataType.Number)
			{
				int integralKey = GetIntegralKey(v.Number);
				if (integralKey > 0)
				{
					return GetNextOf(m_ArrayMap.Find(integralKey));
				}
			}
			return GetNextOf(m_ValueMap.Find(v));
		}

		private TablePair? GetNextOf(LinkedListNode<TablePair> linkedListNode)
		{
			do
			{
				if (linkedListNode == null)
				{
					return null;
				}
				if (linkedListNode.Next == null)
				{
					return TablePair.Nil;
				}
				linkedListNode = linkedListNode.Next;
			}
			while (linkedListNode.Value.Value.IsNil());
			return linkedListNode.Value;
		}

		internal void InitNextArrayKeys(DynValue val, bool lastpos)
		{
			if (val.Type == DataType.Tuple && lastpos)
			{
				DynValue[] tuple = val.Tuple;
				foreach (DynValue val2 in tuple)
				{
					InitNextArrayKeys(val2, lastpos: true);
				}
			}
			else
			{
				Set(++m_InitArray, val.ToScalar());
			}
		}
	}
	[Flags]
	public enum CoreModules
	{
		None = 0,
		Basic = 0x40,
		GlobalConsts = 1,
		TableIterators = 2,
		Metatables = 4,
		String = 8,
		LoadMethods = 0x10,
		Table = 0x20,
		ErrorHandling = 0x80,
		Math = 0x100,
		Coroutine = 0x200,
		Bit32 = 0x400,
		OS_Time = 0x800,
		OS_System = 0x1000,
		IO = 0x2000,
		Debug = 0x4000,
		Dynamic = 0x8000,
		Json = 0x10000,
		Preset_HardSandbox = 0x56B,
		Preset_SoftSandbox = 0x18FEF,
		Preset_Default = 0x1BFFF,
		Preset_Complete = 0x1FFFF
	}
	internal static class CoreModules_ExtensionMethods
	{
		public static bool Has(this CoreModules val, CoreModules flag)
		{
			return (val & flag) == flag;
		}
	}
	public static class ModuleRegister
	{
		public static Table RegisterCoreModules(this Table table, CoreModules modules)
		{
			modules = Script.GlobalOptions.Platform.FilterSupportedCoreModules(modules);
			if (modules.Has(CoreModules.GlobalConsts))
			{
				table.RegisterConstants();
			}
			if (modules.Has(CoreModules.TableIterators))
			{
				table.RegisterModuleType<TableIteratorsModule>();
			}
			if (modules.Has(CoreModules.Basic))
			{
				table.RegisterModuleType<BasicModule>();
			}
			if (modules.Has(CoreModules.Metatables))
			{
				table.RegisterModuleType<MetaTableModule>();
			}
			if (modules.Has(CoreModules.String))
			{
				table.RegisterModuleType<StringModule>();
			}
			if (modules.Has(CoreModules.LoadMethods))
			{
				table.RegisterModuleType<LoadModule>();
			}
			if (modules.Has(CoreModules.Table))
			{
				table.RegisterModuleType<TableModule>();
			}
			if (modules.Has(CoreModules.Table))
			{
				table.RegisterModuleType<TableModule_Globals>();
			}
			if (modules.Has(CoreModules.ErrorHandling))
			{
				table.RegisterModuleType<ErrorHandlingModule>();
			}
			if (modules.Has(CoreModules.Math))
			{
				table.RegisterModuleType<MathModule>();
			}
			if (modules.Has(CoreModules.Coroutine))
			{
				table.RegisterModuleType<CoroutineModule>();
			}
			if (modules.Has(CoreModules.Bit32))
			{
				table.RegisterModuleType<Bit32Module>();
			}
			if (modules.Has(CoreModules.Dynamic))
			{
				table.RegisterModuleType<DynamicModule>();
			}
			if (modules.Has(CoreModules.OS_System))
			{
				table.RegisterModuleType<OsSystemModule>();
			}
			if (modules.Has(CoreModules.OS_Time))
			{
				table.RegisterModuleType<OsTimeModule>();
			}
			if (modules.Has(CoreModules.IO))
			{
				table.RegisterModuleType<IoModule>();
			}
			if (modules.Has(CoreModules.Debug))
			{
				table.RegisterModuleType<DebugModule>();
			}
			if (modules.Has(CoreModules.Json))
			{
				table.RegisterModuleType<JsonModule>();
			}
			return table;
		}

		public static Table RegisterConstants(this Table table)
		{
			DynValue dynValue = DynValue.NewTable(table.OwnerScript);
			Table table2 = dynValue.Table;
			table.Set("_G", DynValue.NewTable(table));
			table.Set("_VERSION", DynValue.NewString(string.Format("MoonSharp {0}", "2.0.0.0")));
			table.Set("_MOONSHARP", dynValue);
			table2.Set("version", DynValue.NewString("2.0.0.0"));
			table2.Set("luacompat", DynValue.NewString("5.2"));
			table2.Set("platform", DynValue.NewString(Script.GlobalOptions.Platform.GetPlatformName()));
			table2.Set("is_aot", DynValue.NewBoolean(Script.GlobalOptions.Platform.IsRunningOnAOT()));
			table2.Set("is_unity", DynValue.NewBoolean(PlatformAutoDetector.IsRunningOnUnity));
			table2.Set("is_mono", DynValue.NewBoolean(PlatformAutoDetector.IsRunningOnMono));
			table2.Set("is_clr4", DynValue.NewBoolean(PlatformAutoDetector.IsRunningOnClr4));
			table2.Set("is_pcl", DynValue.NewBoolean(PlatformAutoDetector.IsPortableFramework));
			table2.Set("banner", DynValue.NewString(Script.GetBanner()));
			return table;
		}

		public static Table RegisterModuleType(this Table gtable, Type t)
		{
			Table table = CreateModuleNamespace(gtable, t);
			foreach (MethodInfo item in from __mi in Framework.Do.GetMethods(t)
				where __mi.IsStatic
				select __mi)
			{
				if (item.GetCustomAttributes(typeof(MoonSharpModuleMethodAttribute), inherit: false).ToArray().Length != 0)
				{
					MoonSharpModuleMethodAttribute moonSharpModuleMethodAttribute = (MoonSharpModuleMethodAttribute)item.GetCustomAttributes(typeof(MoonSharpModuleMethodAttribute), inherit: false).First();
					if (!CallbackFunction.CheckCallbackSignature(item, requirePublicVisibility: true))
					{
						throw new ArgumentException($"Method {item.Name} does not have the right signature.");
					}
					Func<ScriptExecutionContext, CallbackArguments, DynValue> callBack = (Func<ScriptExecutionContext, CallbackArguments, DynValue>)Delegate.CreateDelegate(typeof(Func<ScriptExecutionContext, CallbackArguments, DynValue>), item);
					string text = ((!string.IsNullOrEmpty(moonSharpModuleMethodAttribute.Name)) ? moonSharpModuleMethodAttribute.Name : item.Name);
					table.Set(text, DynValue.NewCallback(callBack, text));
				}
				else if (item.Name == "MoonSharpInit")
				{
					object[] parameters = new object[2] { gtable, table };
					item.Invoke(null, parameters);
				}
			}
			foreach (FieldInfo item2 in from _mi in Framework.Do.GetFields(t)
				where _mi.IsStatic && _mi.GetCustomAttributes(typeof(MoonSharpModuleMethodAttribute), inherit: false).ToArray().Length != 0
				select _mi)
			{
				MoonSharpModuleMethodAttribute moonSharpModuleMethodAttribute2 = (MoonSharpModuleMethodAttribute)item2.GetCustomAttributes(typeof(MoonSharpModuleMethodAttribute), inherit: false).First();
				string name = ((!string.IsNullOrEmpty(moonSharpModuleMethodAttribute2.Name)) ? moonSharpModuleMethodAttribute2.Name : item2.Name);
				RegisterScriptField(item2, null, table, t, name);
			}
			foreach (FieldInfo item3 in from _mi in Framework.Do.GetFields(t)
				where _mi.IsStatic && _mi.GetCustomAttributes(typeof(MoonSharpModuleConstantAttribute), inherit: false).ToArray().Length != 0
				select _mi)
			{
				MoonSharpModuleConstantAttribute moonSharpModuleConstantAttribute = (MoonSharpModuleConstantAttribute)item3.GetCustomAttributes(typeof(MoonSharpModuleConstantAttribute), inherit: false).First();
				string name2 = ((!string.IsNullOrEmpty(moonSharpModuleConstantAttribute.Name)) ? moonSharpModuleConstantAttribute.Name : item3.Name);
				RegisterScriptFieldAsConst(item3, null, table, t, name2);
			}
			return gtable;
		}

		private static void RegisterScriptFieldAsConst(FieldInfo fi, object o, Table table, Type t, string name)
		{
			if (fi.FieldType == typeof(string))
			{
				string str = fi.GetValue(o) as string;
				table.Set(name, DynValue.NewString(str));
				return;
			}
			if (fi.FieldType == typeof(double))
			{
				double num = (double)fi.GetValue(o);
				table.Set(name, DynValue.NewNumber(num));
				return;
			}
			throw new ArgumentException($"Field {name} does not have the right type - it must be string or double.");
		}

		private static void RegisterScriptField(FieldInfo fi, object o, Table table, Type t, string name)
		{
			if (fi.FieldType != typeof(string))
			{
				throw new ArgumentException($"Field {name} does not have the right type - it must be string.");
			}
			string code = fi.GetValue(o) as string;
			DynValue value = table.OwnerScript.LoadFunction(code, table, name);
			table.Set(name, value);
		}

		private static Table CreateModuleNamespace(Table gtable, Type t)
		{
			MoonSharpModuleAttribute moonSharpModuleAttribute = (MoonSharpModuleAttribute)Framework.Do.GetCustomAttributes(t, typeof(MoonSharpModuleAttribute), inherit: false).First();
			if (string.IsNullOrEmpty(moonSharpModuleAttribute.Namespace))
			{
				return gtable;
			}
			Table table = null;
			DynValue dynValue = gtable.Get(moonSharpModuleAttribute.Namespace);
			if (dynValue.Type == DataType.Table)
			{
				table = dynValue.Table;
			}
			else
			{
				table = new Table(gtable.OwnerScript);
				gtable.Set(moonSharpModuleAttribute.Namespace, DynValue.NewTable(table));
			}
			DynValue dynValue2 = gtable.RawGet("package");
			if (dynValue2 == null || dynValue2.Type != DataType.Table)
			{
				gtable.Set("package", dynValue2 = DynValue.NewTable(gtable.OwnerScript));
			}
			DynValue dynValue3 = dynValue2.Table.RawGet("loaded");
			if (dynValue3 == null || dynValue3.Type != DataType.Table)
			{
				dynValue2.Table.Set("loaded", dynValue3 = DynValue.NewTable(gtable.OwnerScript));
			}
			dynValue3.Table.Set(moonSharpModuleAttribute.Namespace, DynValue.NewTable(table));
			return table;
		}

		public static Table RegisterModuleType<T>(this Table table)
		{
			return table.RegisterModuleType(typeof(T));
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
	public sealed class MoonSharpModuleMethodAttribute : Attribute
	{
		public string Name { get; set; }
	}
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	public sealed class MoonSharpModuleAttribute : Attribute
	{
		public string Namespace { get; set; }
	}
	public class ScriptGlobalOptions
	{
		public CustomConvertersCollection CustomConverters { get; set; }

		public IPlatformAccessor Platform { get; set; }

		public bool RethrowExceptionNested { get; set; }

		internal ScriptGlobalOptions()
		{
			Platform = PlatformAutoDetector.GetDefaultPlatform();
			CustomConverters = new CustomConvertersCollection();
		}
	}
	public class ScriptOptions
	{
		public IScriptLoader ScriptLoader { get; set; }

		public Action<string> DebugPrint { get; set; }

		public Func<string, string> DebugInput { get; set; }

		public bool Us

System.IO.Compression.dll

Decompiled a week ago
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO.Compression;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;

[assembly: CompilationRelaxations(8)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: ComVisible(false)]
[assembly: CLSCompliant(true)]
[assembly: SecurityTransparent]
[assembly: SecurityRules(SecurityRuleSet.Level2, SkipVerificationInFullTrust = true)]
[assembly: AssemblyTitle("System.IO.Compression.dll")]
[assembly: AssemblyDescription("System.IO.Compression.dll")]
[assembly: AssemblyDefaultAlias("System.IO.Compression.dll")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyProduct("Microsoft® .NET Framework")]
[assembly: AssemblyCopyright("© Microsoft Corporation.  All rights reserved.")]
[assembly: AssemblyFileVersion("4.6.81.0")]
[assembly: AssemblyInformationalVersion("4.6.81.0")]
[assembly: SatelliteContractVersion("4.0.0.0")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyDelaySign(true)]
[assembly: AssemblyKeyFile("f:\\dd\\tools\\devdiv\\EcmaPublicKey.snk")]
[assembly: AssemblySignatureKey("002400000c800000140100000602000000240000525341310008000001000100613399aff18ef1a2c2514a273a42d9042b72321f1757102df9ebada69923e2738406c21e5b801552ab8d200a65a235e001ac9adc25f2d811eb09496a4c6a59d4619589c69f5baf0c4179a47311d92555cd006acc8b5959f2bd6e10e360c34537a1d266da8085856583c85d81da7f3ec01ed9564c58d93d713cd0172c8e23a10f0239b80c96b07736f5d8b022542a4e74251a5f432824318b3539a5a087f8e53d2f135f9ca47f3bb2e10aff0af0849504fb7cea3ff192dc8de0edad64c68efde34c56d302ad55fd6e80f302d5efcdeae953658d3452561b5f36c542efdbdd9f888538d374cef106acf7d93a4445c3c73cd911f0571aaf3d54da12b11ddec375b3", "a5a866e1ee186f807668209f3b11236ace5e21f117803a3143abb126dd035d7d2f876b6938aaf2ee3414d5420d753621400db44a49c486ce134300a2106adb6bdb433590fef8ad5c43cba82290dc49530effd86523d9483c00f458af46890036b0e2c61d077d7fbac467a506eba29e467a87198b053c749aa2a4d2840c784e6d")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: ReferenceAssembly]
[assembly: AssemblyVersion("4.0.0.0")]
[assembly: TypeForwardedTo(typeof(CompressionLevel))]
[assembly: TypeForwardedTo(typeof(CompressionMode))]
[assembly: TypeForwardedTo(typeof(DeflateStream))]
[assembly: TypeForwardedTo(typeof(GZipStream))]
namespace System.IO.Compression;

public class ZipArchive : IDisposable
{
	public ReadOnlyCollection<ZipArchiveEntry> Entries
	{
		get
		{
			/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
		}
	}

	public ZipArchiveMode Mode
	{
		get
		{
			/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
		}
	}

	public ZipArchive(Stream stream)
	{
		/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
	}

	public ZipArchive(Stream stream, ZipArchiveMode mode)
	{
		/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
	}

	public ZipArchive(Stream stream, ZipArchiveMode mode, bool leaveOpen)
	{
		/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
	}

	public ZipArchive(Stream stream, ZipArchiveMode mode, bool leaveOpen, Encoding entryNameEncoding)
	{
		/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
	}

	public ZipArchiveEntry CreateEntry(string entryName)
	{
		/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
	}

	public ZipArchiveEntry CreateEntry(string entryName, CompressionLevel compressionLevel)
	{
		/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
	}

	protected virtual void Dispose(bool disposing)
	{
		/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
	}

	public void Dispose()
	{
		/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
	}

	public ZipArchiveEntry GetEntry(string entryName)
	{
		/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
	}
}
public class ZipArchiveEntry
{
	public ZipArchive Archive
	{
		get
		{
			/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
		}
	}

	public long CompressedLength
	{
		get
		{
			/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
		}
	}

	public string FullName
	{
		get
		{
			/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
		}
		private set
		{
			/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
		}
	}

	public DateTimeOffset LastWriteTime
	{
		get
		{
			/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
		}
		set
		{
			/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
		}
	}

	public long Length
	{
		get
		{
			/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
		}
	}

	public string Name
	{
		get
		{
			/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
		}
	}

	public void Delete()
	{
		/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
	}

	public Stream Open()
	{
		/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
	}

	public override string ToString()
	{
		/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
	}

	private ZipArchiveEntry()
	{
		/*Error: Empty body found. Decompiled assembly might be a reference assembly.*/;
	}
}
public enum ZipArchiveMode
{
	Read,
	Create,
	Update
}