Decompiled source of Lumod v1.1.0
Mods/lumod.dll
Decompiled 3 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BoneLib; using BoneLib.BoneMenu; using BoneLib.Notifications; using Il2CppSLZ.Marrow; using Il2CppSLZ.Marrow.Data; using Il2CppSLZ.Marrow.SceneStreaming; using Il2CppSLZ.Marrow.Warehouse; using LabFusion.RPC; using MelonLoader; using MelonLoader.Utils; using MoonSharp.Interpreter; using MoonSharp.Interpreter.Interop; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.Utilities; using UnityEngine.SceneManagement; using lumod; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Lua modding!!!")] [assembly: AssemblyDescription("Lua modding!!!")] [assembly: AssemblyCompany("mc")] [assembly: AssemblyProduct("Lumod")] [assembly: AssemblyCopyright("Developed by dc@mei_dot_com")] [assembly: AssemblyTrademark("mc")] [assembly: AssemblyFileVersion("1.0.0")] [assembly: MelonInfo(typeof(Main), "Lumod", "1.0.0", "dc@mei_dot_com", "Link")] [assembly: MelonColor(0, 255, 255, 255)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace lumod; internal class Main : MelonMod { internal static class LumodMenu { public static void CreateElements() { //IL_000b: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) Page val = Page.Root.CreatePage("_Lumod", Color.cyan, 0, true); Page val2 = val.CreatePage("How do I use this?", Color.white, 0, true); val2.CreateFunction("RIGHT MENU + RIGHT A + LEFT MENU to reload lua.", Color.white, (Action)null); val2.CreateFunction("If on flatplayer, press L to reload lua.", Color.white, (Action)null); string text = Path.Combine(MelonEnvironment.UserDataDirectory, "Lumod"); Directory.CreateDirectory(text); string[] files = Directory.GetFiles(text, "*.lua"); foreach (string text2 in files) { scriptPages[text2] = val.CreatePage(text2.Replace(text, ""), Color.white, 0, true); } } } public static class Vec { public static Table ToTable(Script s, Vector3 v) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0065: Invalid comparison between Unknown and I4 Table val = new Table(s); val[(object)"x"] = v.x; val[(object)"y"] = v.y; val[(object)"z"] = v.z; DynValue val2 = s.Globals.Get("_VEC_MT"); if ((int)val2.Type == 6) { val.MetaTable = val2.Table; } return val; } public static Vector3 ToVector(Table v) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) return new Vector3((float)v[(object)"x"], (float)v[(object)"y"], (float)v[(object)"z"]); } } [MoonSharpUserData] public class RigidBodyApi { private readonly Script script; private readonly Rigidbody rb; public bool isKinematic { get { return !((Object)(object)rb == (Object)null) && rb.isKinematic; } set { if ((Object)(object)rb != (Object)null) { rb.isKinematic = value; } } } public Table Velocity { get { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rb == (Object)null) { return null; } return ToVecTable(rb.velocity); } set { //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rb == (Object)null) && value != null) { rb.velocity = new Vector3((float)value.Get("x").Number, (float)value.Get("y").Number, (float)value.Get("z").Number); } } } public Table AngVel { get { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rb == (Object)null) { return null; } return ToVecTable(rb.angularVelocity); } set { //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rb == (Object)null) && value != null) { rb.angularVelocity = new Vector3((float)value.Get("x").Number, (float)value.Get("y").Number, (float)value.Get("z").Number); } } } public RigidBodyApi(Script script, Rigidbody rb) { this.script = script; this.rb = rb; } public void Destroy() { if (!((Object)(object)rb == (Object)null)) { Object.Destroy((Object)(object)rb); } } private Table ToVecTable(Vector3 v) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return Vec.ToTable(script, v); } } [MoonSharpUserData] public class ObjectApi { private readonly Script script; private readonly GameObject go; public string Name { get { return ((Object)(object)go == (Object)null) ? null : ((Object)go).name; } set { if ((Object)(object)go != (Object)null) { ((Object)go).name = value; } } } public int Layer { get { return ((Object)(object)go == (Object)null) ? (-1) : go.layer; } set { if ((Object)(object)go != (Object)null) { go.layer = value; } } } public string LayerName => LayerMask.LayerToName(go.layer); public RigidBodyApi Rigidbody => ((Object)(object)go.GetComponent<Rigidbody>() == (Object)null) ? null : new RigidBodyApi(script, go.GetComponent<Rigidbody>()); public Table MatColor { get { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_0061: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)go == (Object)null) { return null; } Renderer component = go.GetComponent<Renderer>(); if ((Object)(object)component == (Object)null) { return null; } return ToVecTable(new Vector3(component.material.color.r, component.material.color.g, component.material.color.b)); } set { //IL_006a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)go == (Object)null)) { Renderer component = go.GetComponent<Renderer>(); if (!((Object)(object)component == (Object)null)) { component.material.color = new Color((float)value.Get("x").Number, (float)value.Get("y").Number, (float)value.Get("z").Number, 1f); } } } } public ObjectApi Parent { get { if ((Object)(object)go == (Object)null || (Object)(object)go.transform.parent == (Object)null) { return null; } return new ObjectApi(script, ((Component)go.transform.parent).gameObject); } } public ObjectApi Root { get { if ((Object)(object)go == (Object)null) { return null; } return new ObjectApi(script, ((Component)go.transform.root).gameObject); } } public Table Children { get { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown if ((Object)(object)go == (Object)null) { return null; } Table val = new Table(script); for (int i = 0; i < go.transform.childCount; i++) { val.Append(DynValue.FromObject(script, (object)new ObjectApi(script, ((Component)go.transform.GetChild(i)).gameObject))); } return val; } } public Table Forward => ((Object)(object)go == (Object)null) ? null : ToVecTable(go.transform.forward); public Table Right => ((Object)(object)go == (Object)null) ? null : ToVecTable(go.transform.right); public Table Position { get { //IL_001a: Unknown result type (might be due to invalid IL or missing references) return ((Object)(object)go == (Object)null) ? null : ToVecTable(go.transform.position); } set { //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)go == (Object)null) && value != null) { float num = (float)value.Get("x").Number; float num2 = (float)value.Get("y").Number; float num3 = (float)value.Get("z").Number; go.transform.position = new Vector3(num, num2, num3); } } } public Table Rotation { get { //IL_001a: Unknown result type (might be due to invalid IL or missing references) return ((Object)(object)go == (Object)null) ? null : ToVecTable(go.transform.eulerAngles); } set { //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)go == (Object)null) && value != null) { float num = (float)value.Get("x").Number; float num2 = (float)value.Get("y").Number; float num3 = (float)value.Get("z").Number; go.transform.eulerAngles = new Vector3(num, num2, num3); } } } public Table LocalScale { get { //IL_001a: Unknown result type (might be due to invalid IL or missing references) return ((Object)(object)go == (Object)null) ? null : ToVecTable(go.transform.localScale); } set { //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)go == (Object)null) && value != null) { float num = (float)value.Get("x").Number; float num2 = (float)value.Get("y").Number; float num3 = (float)value.Get("z").Number; go.transform.localScale = new Vector3(num, num2, num3); } } } public override string ToString() { return ((Object)(object)go == (Object)null) ? "ObjectApi(dead)" : ("ObjectApi(" + ((Object)go).name + ")"); } public ObjectApi(Script script, GameObject go) { this.script = script; this.go = go; } public void Destroy() { if (!((Object)(object)go == (Object)null)) { Object.Destroy((Object)(object)go); } } public ObjectApi FindChild(string name) { return new ObjectApi(script, ((Component)go.transform.Find(name)).gameObject); } private Table ToVecTable(Vector3 v) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return Vec.ToTable(script, v); } } [MoonSharpUserData] public class CameraApi { private readonly Script script; private readonly Camera camera; public ObjectApi GameObject => new ObjectApi(script, ((Component)camera).gameObject); public int CullingMask { get { return camera.cullingMask; } set { camera.cullingMask = value; } } public Table BackgroundColor { get { //IL_0007: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown return new Table(script) { [(object)"x"] = camera.backgroundColor.r, [(object)"y"] = camera.backgroundColor.g, [(object)"z"] = camera.backgroundColor.b }; } set { //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (value != null) { float num = (float)value.Get("x").Number; float num2 = (float)value.Get("y").Number; float num3 = (float)value.Get("z").Number; camera.backgroundColor = new Color(num, num2, num3); } } } public int ClearFlags { get { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected I4, but got Unknown return (int)camera.clearFlags; } set { camera.clearFlags = (CameraClearFlags)value; } } public CameraApi(Script script, Camera camera) { this.script = script; this.camera = camera; } } [MoonSharpUserData] public class PlayerApi { private readonly Script script; public CameraApi MainCamera { get { Camera componentInChildren = ((Component)Player.ControllerRig).gameObject.GetComponentInChildren<Camera>(); if ((Object)(object)componentInChildren == (Object)null) { return null; } return new CameraApi(script, componentInChildren); } } public CameraApi SpectatorCamera { get { Camera componentInChildren = GameObject.Find("GameplaySystems [0]/DisabledContainer/Spectator Camera/").GetComponentInChildren<Camera>(); if ((Object)(object)componentInChildren == (Object)null) { return null; } return new CameraApi(script, componentInChildren); } } public ObjectApi RigManager => new ObjectApi(script, ((Component)Player.RigManager).gameObject); public ObjectApi PhysicsRig => new ObjectApi(script, ((Component)Player.PhysicsRig).gameObject); public float Health { get { if ((Object)(object)Player.RigManager.health == (Object)null) { return 1f; } return Player.RigManager.health.curr_Health; } set { if (value > 0f) { Player.RigManager.health.alive = true; Player.RigManager.health.deathIsImminent = false; Player.RigManager.health.Respawn(); } Player.RigManager.health.curr_Health = value; } } public float MaxHealth { get { if ((Object)(object)Player.RigManager.health == (Object)null) { return 1f; } return Player.RigManager.health.max_Health; } set { Player.RigManager.health.max_Health = value; } } public ObjectApi RightHand { get { Hand rightHand = Player.RightHand; if ((Object)(object)rightHand == (Object)null) { return null; } return new ObjectApi(script, ((Component)rightHand).gameObject); } } public ObjectApi LeftHand { get { Hand leftHand = Player.LeftHand; if ((Object)(object)leftHand == (Object)null) { return null; } return new ObjectApi(script, ((Component)leftHand).gameObject); } } public ObjectApi Head { get { Transform head = Player.Head; if ((Object)(object)head == (Object)null) { return null; } return new ObjectApi(script, ((Component)head).gameObject); } } public ObjectApi Chest { get { Transform chest = Player.Chest; if ((Object)(object)chest == (Object)null) { return null; } return new ObjectApi(script, ((Component)chest).gameObject); } } public ObjectApi Pelvis { get { Transform pelvis = ((Rig)Player.PhysicsRig).m_pelvis; if ((Object)(object)pelvis == (Object)null) { return null; } return new ObjectApi(script, ((Component)pelvis).gameObject); } } public ObjectApi Feet { get { GameObject feet = Player.PhysicsRig.feet; if ((Object)(object)feet == (Object)null) { return null; } return new ObjectApi(script, feet.gameObject); } } public ObjectApi LeftShoulder { get { Transform shoulderLf = ((Rig)Player.PhysicsRig).m_shoulderLf; if ((Object)(object)shoulderLf == (Object)null) { return null; } return new ObjectApi(script, ((Component)shoulderLf).gameObject); } } public ObjectApi RightShoulder { get { Transform shoulderRt = ((Rig)Player.PhysicsRig).m_shoulderRt; if ((Object)(object)shoulderRt == (Object)null) { return null; } return new ObjectApi(script, ((Component)shoulderRt).gameObject); } } public ObjectApi LeftElbow { get { Transform elbowLf = ((Rig)Player.PhysicsRig).m_elbowLf; if ((Object)(object)elbowLf == (Object)null) { return null; } return new ObjectApi(script, ((Component)elbowLf).gameObject); } } public ObjectApi RightElbow { get { Transform elbowRt = ((Rig)Player.PhysicsRig).m_elbowRt; if ((Object)(object)elbowRt == (Object)null) { return null; } return new ObjectApi(script, ((Component)elbowRt).gameObject); } } public ObjectApi LeftHip { get { Transform hipLf = ((Rig)Player.PhysicsRig).m_hipLf; if ((Object)(object)hipLf == (Object)null) { return null; } return new ObjectApi(script, ((Component)hipLf).gameObject); } } public ObjectApi RightHip { get { Transform hipRt = ((Rig)Player.PhysicsRig).m_hipRt; if ((Object)(object)hipRt == (Object)null) { return null; } return new ObjectApi(script, ((Component)hipRt).gameObject); } } public ObjectApi LeftKnee { get { Transform kneeLf = ((Rig)Player.PhysicsRig).m_kneeLf; if ((Object)(object)kneeLf == (Object)null) { return null; } return new ObjectApi(script, ((Component)kneeLf).gameObject); } } public ObjectApi RightKnee { get { Transform kneeRt = ((Rig)Player.PhysicsRig).m_kneeRt; if ((Object)(object)kneeRt == (Object)null) { return null; } return new ObjectApi(script, ((Component)kneeRt).gameObject); } } public ObjectApi LeftFoot { get { Transform footLf = ((Rig)Player.PhysicsRig).m_footLf; if ((Object)(object)footLf == (Object)null) { return null; } return new ObjectApi(script, ((Component)footLf).gameObject); } } public ObjectApi RightFoot { get { Transform footRt = ((Rig)Player.PhysicsRig).m_footRt; if ((Object)(object)footRt == (Object)null) { return null; } return new ObjectApi(script, ((Component)footRt).gameObject); } } public PlayerApi(Script script) { this.script = script; } public void Revive() { Player.RigManager.health.Respawn(); } public void Teleport(Table pos) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) if (pos != null && !((Object)(object)Player.RigManager == (Object)null)) { float num = (float)pos.Get("x").Number; float num2 = (float)pos.Get("y").Number; float num3 = (float)pos.Get("z").Number; Player.RigManager.Teleport(new Vector3(num, num2, num3), true); } } } [MoonSharpUserData] public class InputApi { private readonly Script script; public InputApi(Script script) { this.script = script; } public bool KeyDown(string name) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) Keyboard current = Keyboard.current; if (current == null) { return false; } if (!Enum.TryParse<Key>(name, ignoreCase: true, out Key result)) { return false; } return ((ButtonControl)current[result]).wasPressedThisFrame; } public bool KeyHeld(string name) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) Keyboard current = Keyboard.current; if (current == null) { return false; } if (!Enum.TryParse<Key>(name, ignoreCase: true, out Key result)) { return false; } return ((ButtonControl)current[result]).isPressed; } public string CurrentKey() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) Keyboard current = Keyboard.current; if (current == null) { return null; } Enumerator<KeyControl> enumerator = current.allKeys.GetEnumerator(); while (enumerator.MoveNext()) { KeyControl current2 = enumerator.Current; if (((ButtonControl)current2).isPressed) { return ((object)current2.keyCode/*cast due to .constrained prefix*/).ToString(); } } return null; } public bool RightMenuDown() { return (Object)(object)Player.RightHand != (Object)null && Player.RightController.GetBButtonDown(); } public bool RightMenuHeld() { return (Object)(object)Player.RightController != (Object)null && Player.RightController.GetBButton(); } public bool LeftMenuDown() { return (Object)(object)Player.LeftController != (Object)null && Player.LeftController.GetBButtonDown(); } public bool LeftMenuHeld() { return (Object)(object)Player.LeftController != (Object)null && Player.LeftController.GetBButton(); } public bool RightADown() { return (Object)(object)Player.RightController != (Object)null && Player.RightController.GetAButtonDown(); } public bool RightAHeld() { return (Object)(object)Player.RightController != (Object)null && Player.RightController.GetAButton(); } public bool LeftADown() { return (Object)(object)Player.LeftController != (Object)null && Player.LeftController.GetAButtonDown(); } public bool LeftAHeld() { return (Object)(object)Player.LeftController != (Object)null && Player.LeftController.GetAButton(); } public bool RightStickDown() { return (Object)(object)Player.RightController != (Object)null && Player.RightController.GetThumbStickDown(); } public bool LeftStickDown() { return (Object)(object)Player.LeftController != (Object)null && Player.LeftController.GetThumbStickDown(); } public Table RightStickAxis() { //IL_0019: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.RightController == (Object)null) { return null; } Vector2 thumbStickAxis = Player.RightController.GetThumbStickAxis(); Table val = new Table(script); val[(object)"x"] = thumbStickAxis.x; val[(object)"y"] = thumbStickAxis.y; return val; } public Table LeftStickAxis() { //IL_0019: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.LeftController == (Object)null) { return null; } Vector2 thumbStickAxis = Player.LeftController.GetThumbStickAxis(); Table val = new Table(script); val[(object)"x"] = thumbStickAxis.x; val[(object)"y"] = thumbStickAxis.y; return val; } public bool RightTriggerDown() { return (Object)(object)Player.RightController != (Object)null && Player.RightHand._indexButtonDown; } public bool LeftTriggerDown() { return (Object)(object)Player.LeftController != (Object)null && Player.LeftHand._indexButtonDown; } public float RightTriggerValue() { return ((Object)(object)Player.RightController != (Object)null) ? Player.RightHand._indexTriggerAxis : 0f; } public float LeftTriggerValue() { return ((Object)(object)Player.LeftController != (Object)null) ? Player.LeftHand._indexTriggerAxis : 0f; } } [MoonSharpUserData] public class DebugApi { private readonly Script script; public DebugApi(Script script) { this.script = script; } public ObjectApi DrawLine(Table fromt, Table tot, Table color, float alpha = 1f, float startWidth = 0.01f, float endWidth = 0.01f) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ToVector3(fromt); Vector3 val2 = ToVector3(tot); Color val3 = default(Color); ((Color)(ref val3))..ctor((float)color.Get("x").Number, (float)color.Get("y").Number, (float)color.Get("z").Number, alpha); GameObject val4 = new GameObject("DebugLine"); LineRenderer val5 = val4.AddComponent<LineRenderer>(); val5.positionCount = 2; val5.useWorldSpace = true; val5.startWidth = startWidth; val5.endWidth = endWidth; ((Renderer)val5).material = new Material(Shader.Find("Sprites/Default")); Color startColor = (val5.endColor = val3); val5.startColor = startColor; val5.SetPosition(0, val); val5.SetPosition(1, val2); return new ObjectApi(script, val4); } public ObjectApi DrawSphere(Table pos, Table size, Table color, float alpha = 1f) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) GameObject val = GameObject.CreatePrimitive((PrimitiveType)0); ((Collider)val.GetComponent<SphereCollider>()).enabled = false; val.transform.position = ToVector3(pos); val.transform.localScale = ToVector3(size); Renderer component = val.GetComponent<Renderer>(); component.material = new Material(Shader.Find("UI/Default")); component.material.color = new Color((float)color.Get("x").Number, (float)color.Get("y").Number, (float)color.Get("z").Number, alpha); return new ObjectApi(script, val); } } [MoonSharpUserData] public class CrateApi { private readonly Script script; public CrateApi(Script script) { this.script = script; } public void Spawn(string barcode, Table pos, Table rotation, DynValue spawnCallback = null) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_003b: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) Action<ObjectApi> onSpawned = delegate(ObjectApi obj) { //IL_004a: Expected O, but got Unknown //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 if (spawnCallback == null || (int)spawnCallback.Type != 5) { return; } try { script.Call(spawnCallback, new object[1] { obj }); } catch (ScriptRuntimeException ex) { ScriptRuntimeException ex2 = ex; MelonLogger.Error(((InterpreterException)ex2).DecoratedMessage); } }; Spawnable spawnable = new Spawnable { crateRef = new SpawnableCrateReference(barcode) }; NetworkAssetSpawner.Spawn(new SpawnRequestInfo { Spawnable = spawnable, Position = ToVector3(pos), Rotation = Quaternion.Euler(ToVector3(rotation)), SpawnCallback = delegate(SpawnCallbackInfo info) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (onSpawned != null && (Object)(object)info.Spawned != (Object)null) { script.Call((object)onSpawned, new object[1] { DynValue.FromObject(script, (object)new ObjectApi(script, info.Spawned)) }); } } }); } } [MoonSharpUserData] public class MelonPageApi { private readonly Script script; private readonly Page page; public MelonPageApi(Script script, Page page) { this.script = script; this.page = page; } public void CreateFunction(string name, Table color, DynValue callback) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if (callback == null || (int)callback.Type != 5) { return; } Color val = default(Color); ((Color)(ref val))..ctor((float)color.Get("x").Number, (float)color.Get("y").Number, (float)color.Get("z").Number); page.CreateFunction(name, val, (Action)delegate { //IL_001d: Expected O, but got Unknown try { script.Call(callback); } catch (ScriptRuntimeException ex) { ScriptRuntimeException ex2 = ex; MelonLogger.Error(((InterpreterException)ex2).DecoratedMessage); } }); if (page.Color == Color.white) { page.Color = Color.cyan; } } } internal const string Name = "Lumod"; internal const string Description = "Lua modding!!!"; internal const string Author = "dc@mei_dot_com"; internal const string Company = "mc"; internal const string Version = "1.0.0"; internal const string DownloadLink = "Link"; private List<DynValue> updateHandlers = new List<DynValue>(); private List<DynValue> fixedUpdateHandlers = new List<DynValue>(); private List<DynValue> sceneHandlers = new List<DynValue>(); private List<DynValue> keyHandlers = new List<DynValue>(); private static Dictionary<string, Page> scriptPages = new Dictionary<string, Page>(); private bool done = false; public static Vector3 ToVector3(Table t) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) return new Vector3((float)t.Get("x").Number, (float)t.Get("y").Number, (float)t.Get("z").Number); } public override void OnEarlyInitializeMelon() { ((MelonBase)this).OnEarlyInitializeMelon(); } private void LoadScripts() { //IL_005e: Expected O, but got Unknown string path = Path.Combine(MelonEnvironment.UserDataDirectory, "Lumod"); Directory.CreateDirectory(path); string[] files = Directory.GetFiles(path, "*.lua"); foreach (string text in files) { MelonLogger.Msg("Loading " + text); Script val = MakeScript(text); try { val.DoString(File.ReadAllText(text), (Table)null, text); } catch (InterpreterException ex) { InterpreterException ex2 = ex; MelonLogger.Error("[" + text + "]\n" + ex2.DecoratedMessage); } } } public Table Raycast(Script s, Vector3 origin, Vector3 direction, float distance, int layerMask = -1) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) RaycastHit val = default(RaycastHit); if (Physics.Raycast(origin, direction, ref val, distance, layerMask)) { ObjectApi objectApi = new ObjectApi(s, ((Component)((RaycastHit)(ref val)).collider).gameObject); Table val2 = new Table(s); val2[(object)"obj"] = objectApi; val2[(object)"distance"] = ((RaycastHit)(ref val)).distance; val2[(object)"point"] = Vec.ToTable(s, ((RaycastHit)(ref val)).point); val2[(object)"layer"] = ((Component)((RaycastHit)(ref val)).collider).gameObject.layer; val2[(object)"normal"] = Vec.ToTable(s, ((RaycastHit)(ref val)).normal); return val2; } return null; } public override void OnInitializeMelon() { ((MelonBase)this).OnInitializeMelon(); } private Script MakeScript(string file) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown Script scr = new Script(); scr.Globals[(object)"player"] = new PlayerApi(scr); scr.Globals[(object)"page"] = new MelonPageApi(scr, scriptPages[file]); scr.Globals[(object)"crate"] = new CrateApi(scr); scr.Globals[(object)"debug"] = new DebugApi(scr); scr.Globals[(object)"input"] = new InputApi(scr); scr.Globals[(object)"player"] = new PlayerApi(scr); scr.Globals[(object)"onUpdate"] = (Action<DynValue>)delegate(DynValue fn) { updateHandlers.Add(fn); }; scr.Globals[(object)"onKeyDown"] = (Action<DynValue>)delegate(DynValue fn) { keyHandlers.Add(fn); }; scr.Globals[(object)"onSceneWasLoaded"] = (Action<DynValue>)delegate(DynValue fn) { sceneHandlers.Add(fn); }; scr.Globals[(object)"print"] = DynValue.NewCallback((Func<ScriptExecutionContext, CallbackArguments, DynValue>)delegate(ScriptExecutionContext ctx, CallbackArguments args) { List<string> list = new List<string>(); string oldValue = Path.Combine(MelonEnvironment.UserDataDirectory, "Lumod"); for (int i = 0; i < args.Count; i++) { list.Add(args[i].ToPrintString()); } MelonLogger.Msg("[" + file.Replace(oldValue, "") + "] " + string.Join("\t", list)); return DynValue.Nil; }, (string)null); scr.Globals[(object)"error"] = (Action<string>)delegate(string s) { MelonLogger.Error(s); }; scr.Globals[(object)"warn"] = (Action<string>)delegate(string s) { MelonLogger.Warning(s); }; scr.Globals[(object)"loadSceneBarcode"] = (Action<string>)delegate(string s) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown SceneStreamer.Load(new Barcode(s), (Barcode)null); }; scr.Globals[(object)"loadSceneDirect"] = (Action<string>)delegate(string s) { SceneManager.LoadScene(s); }; scr.Globals[(object)"notify"] = (Action<string, string, NotificationType, float>)delegate(string msg, string title, NotificationType type, float len) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) Notify(msg, title, type, len); }; scr.Globals[(object)"raycast"] = (Func<Table, Table, float, Table>)delegate(Table originTable, Table directionTable, float distance) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) Vector3 origin = default(Vector3); ((Vector3)(ref origin))..ctor((float)originTable.Get("x").Number, (float)originTable.Get("y").Number, (float)originTable.Get("z").Number); Vector3 direction = default(Vector3); ((Vector3)(ref direction))..ctor((float)directionTable.Get("x").Number, (float)directionTable.Get("y").Number, (float)directionTable.Get("z").Number); return Raycast(scr, origin, direction, distance); }; scr.Globals[(object)"time"] = (Func<long>)(() => DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()); scr.Globals[(object)"filepath"] = (Func<string, string>)((string f) => Path.Combine(MelonEnvironment.UserDataDirectory, "Lumod", f)); scr.Globals[(object)"vec"] = (Func<float, float, float, Table>)delegate(float x, float y, float z) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Invalid comparison between Unknown and I4 Table val = new Table(scr); val[(object)"x"] = x; val[(object)"y"] = y; val[(object)"z"] = z; DynValue val2 = scr.Globals.Get("VectorMetatable"); val.MetaTable = ((val2 != null && (int)val2.Type == 6) ? val2.Table : null); return val; }; scr.Globals[(object)"import"] = (Func<string, DynValue>)((string name) => UserData.CreateStatic((from a in AppDomain.CurrentDomain.GetAssemblies() select a.GetType(name)).FirstOrDefault((Type t) => t != null))); scr.Globals[(object)"getScene"] = (Func<string>)delegate { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).name; }; scr.Globals[(object)"_NOTIFY_SUCCESS"] = (object)(NotificationType)3; scr.Globals[(object)"_NOTIFY_ERROR"] = (object)(NotificationType)2; scr.Globals[(object)"_NOTIFY_INFO"] = (object)(NotificationType)0; scr.Globals[(object)"_NOTIFY_WARNING"] = (object)(NotificationType)1; scr.DoString("\r\n local mt = {}\r\n mt.__index = mt\r\n\r\n function vec(x, y, z)\r\n return setmetatable({x = x or 0, y = y or 0, z = z or 0}, mt)\r\n end\r\n\r\n mt.__add = function(a, b) return vec(a.x + b.x, a.y + b.y, a.z + b.z) end\r\n mt.__sub = function(a, b) return vec(a.x - b.x, a.y - b.y, a.z - b.z) end\r\n mt.__unm = function(a) return vec(-a.x, -a.y, -a.z) end\r\n mt.__mul = function(a, b)\r\n if type(a) == 'number' then return vec(a * b.x, a * b.y, a * b.z) end\r\n if type(b) == 'number' then return vec(a.x * b, a.y * b, a.z * b) end\r\n return vec(a.x * b.x, a.y * b.y, a.z * b.z)\r\n end\r\n mt.__eq = function(a, b) return a.x == b.x and a.y == b.y and a.z == b.z end\r\n mt.__tostring = function(a) return '(' .. a.x .. ', ' .. a.y .. ', ' .. a.z .. ')' end\r\n\r\n function mt:length() return math.sqrt(self.x^2 + self.y^2 + self.z^2) end\r\n function mt:dot(b) return self.x * b.x + self.y * b.y + self.z * b.z end\r\n\r\n _VEC_MT = mt\r\n", (Table)null, (string)null); return scr; } public override void OnLateInitializeMelon() { ((MelonBase)this).OnLateInitializeMelon(); UserData.RegistrationPolicy = InteropRegistrationPolicy.Automatic; UserData.RegisterType<InputApi>((InteropAccessMode)7, (string)null); UserData.RegisterType<PlayerApi>((InteropAccessMode)7, (string)null); UserData.RegisterType<Vector3>((InteropAccessMode)7, (string)null); UserData.RegisterType<ObjectApi>((InteropAccessMode)7, (string)null); UserData.RegisterType<CameraApi>((InteropAccessMode)7, (string)null); UserData.RegisterType<RigidBodyApi>((InteropAccessMode)7, (string)null); UserData.RegisterType<DebugApi>((InteropAccessMode)7, (string)null); UserData.RegisterType<CrateApi>((InteropAccessMode)7, (string)null); UserData.RegisterType<MelonPageApi>((InteropAccessMode)7, (string)null); LumodMenu.CreateElements(); LoadScripts(); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { //IL_0040: Expected O, but got Unknown ((MelonMod)this).OnSceneWasLoaded(buildIndex, sceneName); foreach (DynValue sceneHandler in sceneHandlers) { try { sceneHandler.Function.Call(new object[2] { sceneHandler, sceneName }); } catch (ScriptRuntimeException ex) { ScriptRuntimeException ex2 = ex; MelonLogger.Error(((InterpreterException)ex2).DecoratedMessage); } } } private void Notify(string msg, string title, NotificationType type, float len) { //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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown Notification val = new Notification { Title = NotificationText.op_Implicit(title), Message = NotificationText.op_Implicit(msg), Type = type, ShowTitleOnPopup = true, PopupLength = len }; Notifier.Send(val); } public override void OnUpdate() { //IL_00b1: Expected O, but got Unknown //IL_028b: Expected O, but got Unknown //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) ((MelonBase)this).OnUpdate(); if (!done) { GameObject val = GameObject.Find("GameplaySystems [0]/DisabledContainer/[UIRig]/PLAYERUI/UI_PREFERENCES/scaleOffset/canvas_UI/group_Options/panel_Preferences/[BoneMenu] - Canvas(Clone)"); if ((Object)(object)val != (Object)null) { foreach (Transform componentsInChild in val.GetComponentsInChildren<Transform>(true)) { ((Component)componentsInChild).gameObject.layer = 5; } done = true; } } foreach (DynValue updateHandler in updateHandlers) { try { updateHandler.Function.Call((DynValue[])(object)new DynValue[1] { updateHandler }); } catch (ScriptRuntimeException ex) { ScriptRuntimeException ex2 = ex; MelonLogger.Error(((InterpreterException)ex2).DecoratedMessage); } } if ((Keyboard.current != null && ((ButtonControl)Keyboard.current.lKey).wasPressedThisFrame) || (Player.HandsExist && Player.RightController.GetAButton() && Player.RightController.GetBButton() && Player.LeftController.GetBButtonDown())) { MelonLogger.Msg("Reloading lua"); for (int i = 0; i < scriptPages.Count; i++) { Page value = scriptPages.ElementAt(i).Value; value.RemoveAll(); } updateHandlers = new List<DynValue>(); sceneHandlers = new List<DynValue>(); keyHandlers = new List<DynValue>(); try { LoadScripts(); Notify("Reloaded Lua scripts", "Lumod", (NotificationType)3, 0.55f); } catch (Exception ex3) { MelonLogger.Error(ex3.ToString()); Notify("Error reloading lua: " + ex3.Message, "Lumod", (NotificationType)2, 2f); } } Keyboard current3 = Keyboard.current; if (current3 == null) { return; } ReadOnlyArray<KeyControl> allKeys = current3.allKeys; for (int j = 0; j < allKeys.Count; j++) { KeyControl val2 = allKeys[j]; if (!((ButtonControl)val2).wasPressedThisFrame) { continue; } string text = ((object)val2.keyCode/*cast due to .constrained prefix*/).ToString(); foreach (DynValue keyHandler in keyHandlers) { try { keyHandler.Function.Call(new object[2] { keyHandler, text }); } catch (ScriptRuntimeException ex4) { ScriptRuntimeException ex5 = ex4; MelonLogger.Error(((InterpreterException)ex5).DecoratedMessage); } } } } public override void OnFixedUpdate() { //IL_003a: Expected O, but got Unknown ((MelonBase)this).OnFixedUpdate(); foreach (DynValue fixedUpdateHandler in fixedUpdateHandlers) { try { fixedUpdateHandler.Function.Call((DynValue[])(object)new DynValue[1] { fixedUpdateHandler }); } catch (ScriptRuntimeException ex) { ScriptRuntimeException ex2 = ex; MelonLogger.Error(((InterpreterException)ex2).DecoratedMessage); } } } public override void OnLateUpdate() { ((MelonBase)this).OnLateUpdate(); } }
UserLibs/MoonSharp.Interpreter.dll
Decompiled 3 days ago
The result has been truncated due to the large size, download it to view full contents!
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