Example #1
0
        /// <summary>
        /// Set the actor's position
        /// </summary>
        /// <sqparam type="Vector3" name="position" optional=false>The Actor's position</sqparam>
        /// <sqreturns></sqreturns>
        private static int SetPosition(Squirrel vm, int argCount)
        {
            var self          = (SqInstance)ScriptHandler.This;
            var argPosition   = ScriptHandler.GetArg <Vector3>(0);
            var internalActor = self[RegisteredClass.HndInternalActor];

            return(0);
        }
Example #2
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <sqparam type="Vector3" name="position" optional=false>The Actor's position</sqparam>
        /// <sqreturns></sqreturns>
        private static int Constructor(Squirrel vm, int argCount)
        {
            var self        = (SqInstance)ScriptHandler.This;
            var argPosition = ScriptHandler.GetArg <Vector3>(0);

            self.CallMember(RegisteredClass.HndSetPosition, argPosition);
            self.CallMember(RegisteredClass.SetHealth, 100);
            return(0);
        }
Example #3
0
        private static SqTable MakeMethods(Type type)
        {
            var methods = new SqTable();
            // Get all methods by name
            var dict = new Dictionary <string, List <MethodInfo> >();

            foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance))
            {
                if (dict.TryGetValue(method.Name, out var already))
                {
                    already.Add(method);
                    continue;
                }
                var list = new List <MethodInfo> {
                    method
                };
                dict.Add(method.Name, list);
            }
            // Convert methods
            foreach (var kvp in dict)
            {
                var name      = kvp.Key;
                var overrides = kvp.Value;
                methods[name] = ScriptHandler.MakeFunction(
                    (vm, argCount) =>
                {
                    var self     = (SqHostObject)ScriptHandler.This;
                    var possible = overrides
                                   .Where(e => e.GetParameters().Length >= argCount);
                    if (!possible.Any())
                    {
                        throw new Exception($"No matching method {type}.{name} that can consume the given arguments");
                    }
                    var toCall       = possible.OrderBy(e => e.GetParameters().Length).First();
                    var methodParams = toCall.GetParameters();
                    var args         = new object[argCount];
                    for (var i = 0; i < argCount; i++)
                    {
                        args[i] = ScriptHandler.GetArg(i, methodParams[i].ParameterType, true);
                    }
                    try
                    {
                        vm.PushDynamic(toCall.Invoke(self.Object, args));
                    }
                    catch (TargetParameterCountException e)
                    {
                        throw new Exception($"Cannot call \"{name}\" with {argCount} arguments");
                    }
                    return(1);
                }
                    );
            }
            return(methods);
        }
Example #4
0
        public static int Constructor(Squirrel vm, int argCount)
        {
            var self     = ((SqInstance)ScriptHandler.This);
            var duration = ScriptHandler.GetArg <double>(0);
            var times    = ScriptHandler.GetArg <int>(1);
            var func     = ScriptHandler.GetArg <SqClosure>(2);

            Timers.Add(self, GameScene.Current.TimerHandler.StartTimer(
                           duration, (_) =>
            {
                func.CallAsMethod(self);
                if (Timers[self].Times == 1)
                {
                    Timers.Remove(self);
                }
            }
                           ));
            return(0);
        }
Example #5
0
        public static SqTable GetDelegate(Type type)
        {
            if (Delegates.TryGetValue(type, out var already))
            {
                return(already);
            }
            var del = new SqTable();

            // Add methods and properties
            del["_methods"] = MakeMethods(type);
            del["_props"]   = MakeProperties(type);
            // Add metamethods for accessing properties/methods
            del["_set"] = ScriptHandler.MakeFunction(
                (vm, _) =>
            {
                var self = (SqHostObject)ScriptHandler.This;
                var key  = ScriptHandler.GetArg(0);
                var val  = ScriptHandler.GetArg(1);
                // Look for property
                var props = self["_props"] as SqTable;
                if (props.TryGetValue(ScriptHandler.GetArg(0), out var prop))
                {
                    var set = (prop as SqArray)[0] as SqClosure;
                    set.CallAsMethod(self, val);
                    return(0);
                }
                // Nothing was found
                throw new Exception($"Property \"{self.Object.GetType()}.{key}\" does not exist");
            }
                );
            del["_get"] = ScriptHandler.MakeFunction(
                (vm, _) =>
            {
                var self = (SqHostObject)ScriptHandler.This;
                var key  = ScriptHandler.GetArg(0) as string
                           ?? throw new InvalidOperationException(
                    $"An object of type {self.Object.GetType().Name} " +
                    $"must be indexed only by string values"
                    );
                // Look for method
                var methods = self["_methods"] as SqTable;
                if (methods.TryGetValue(ScriptHandler.GetArg(0), out var method))
                {
                    vm.PushDynamic(method as SqClosure);
                    return(1);
                }
                // Look for property
                var props = self["_props"] as SqTable;
                if (props.TryGetValue(ScriptHandler.GetArg(0), out var prop))
                {
                    var get = (prop as SqArray)[1] as SqClosure;
                    vm.PushDynamic(get.CallAsMethod(self)[0]);
                    return(1);
                }
                // Nothing was found
                throw new Exception($"Method/property \"{self.Object.GetType()}.{key}\" does not exist");
            }
                );
            // Operators
            del["_add"] = ScriptHandler.MakeFunction(
                (vm, _) =>
            {
                var self   = ((SqHostObject)ScriptHandler.This).Object;
                var other  = ScriptHandler.GetArg <object>(0);
                var method = type.GetMethod("op_Addition", new Type[] { type, other.GetType() });
                if (method is null)
                {
                    throw new Exception($"Operator is not defined: {type.Name} + {other.GetType().Name}");
                }
                vm.PushDynamic(method.Invoke(null, new object[] { self, other }));
                return(1);
            }
                );
            del["_sub"] = ScriptHandler.MakeFunction(
                (vm, _) =>
            {
                var self   = ((SqHostObject)ScriptHandler.This).Object;
                var other  = ScriptHandler.GetArg <object>(0);
                var method = type.GetMethod("op_Subtraction", new Type[] { type, other.GetType() });
                if (method is null)
                {
                    throw new Exception($"Operator is not defined: {type.Name} - {other.GetType().Name}");
                }
                vm.PushDynamic(method.Invoke(null, new object[] { self, other }));
                return(1);
            }
                );
            del["_mul"] = ScriptHandler.MakeFunction(
                (vm, _) =>
            {
                var self   = ((SqHostObject)ScriptHandler.This).Object;
                var other  = ScriptHandler.GetArg <object>(0);
                var method = type.GetMethod("op_Multiply", new Type[] { type, other.GetType() });
                if (method is null)
                {
                    throw new Exception($"Operator is not defined: {type.Name} * {other.GetType().Name}");
                }
                vm.PushDynamic(method.Invoke(null, new object[] { self, other }));
                return(1);
            }
                );
            del["_div"] = ScriptHandler.MakeFunction(
                (vm, _) =>
            {
                var self   = ((SqHostObject)ScriptHandler.This).Object;
                var other  = ScriptHandler.GetArg <object>(0);
                var method = type.GetMethod("op_Division", new Type[] { type, other.GetType() });
                if (method is null)
                {
                    throw new Exception($"Operator is not defined: {type.Name} / {other.GetType().Name}");
                }
                vm.PushDynamic(method.Invoke(null, new object[] { self, other }));
                return(1);
            }
                );
            del["_modulo"] = ScriptHandler.MakeFunction(
                (vm, _) =>
            {
                var self   = ((SqHostObject)ScriptHandler.This).Object;
                var other  = ScriptHandler.GetArg <object>(0);
                var method = type.GetMethod("op_Modulus", new Type[] { type, other.GetType() });
                if (method is null)
                {
                    throw new Exception($"Operator is not defined: {type.Name} % {other.GetType().Name}");
                }
                vm.PushDynamic(method.Invoke(null, new object[] { self, other }));
                return(1);
            }
                );
            del["_unm"] = ScriptHandler.MakeFunction(
                (vm, _) =>
            {
                var self   = ((SqHostObject)ScriptHandler.This).Object;
                var method = type.GetMethod("op_UnaryNegation", new Type[] { type });
                if (method is null)
                {
                    throw new Exception($"Operator is not defined: -{type.Name}");
                }
                vm.PushDynamic(method.Invoke(null, new object[] { self }));
                return(1);
            }
                );
            del["_typeof"] = ScriptHandler.MakeFunction(
                (vm, _) =>
            {
                var self = ((SqHostObject)ScriptHandler.This).Object;
                vm.PushString(self.GetType().Name, -1);
                return(1);
            }
                );
            del["_tostring"] = ((SqTable)del["_methods"])["ToString"];
            del["_cmp"]      = ScriptHandler.MakeFunction(
                (vm, _) =>
            {
                var self  = ((SqHostObject)ScriptHandler.This).Object;
                var other = ScriptHandler.GetArg <object>(0);
                if (self is IComparable comparableSelf)
                {
                    vm.PushDynamic(comparableSelf.CompareTo(other));
                    return(1);
                }
                var eqMethod = type.GetMethod("op_Equality", new Type[] { type, other.GetType() });
                if (!(eqMethod is null))
                {
                    if ((bool)eqMethod.Invoke(null, new object[] { self, other }))
                    {
                        vm.PushDynamic(0);
                        return(1);
                    }
                    var gtMethod = type.GetMethod("op_GreaterThan", new Type[] { type, other.GetType() });
                    if (!(gtMethod is null))
                    {
                        if ((bool)gtMethod.Invoke(null, new object[] { self, other }))
                        {
                            vm.PushDynamic(1);
                            return(1);
                        }
                        vm.PushDynamic(-1);
                        return(1);
                    }
                    var ltMethod = type.GetMethod("op_LessThan", new Type[] { type, other.GetType() });
                    if (!(ltMethod is null))
                    {
                        if ((bool)ltMethod.Invoke(null, new object[] { self, other }))
                        {
                            vm.PushDynamic(-1);
                            return(1);
                        }
                        vm.PushDynamic(1);
                        return(1);
                    }
                    throw new Exception($"No < or > operator defined for left-hand type {type.Name} " +
                                        $"&& right-hand type {other.GetType().Name}");
                }
                throw new Exception($"Operator is not defined: {type.Name} == {other.GetType().Name}");
            }
                );
            del["BOr"] = ScriptHandler.MakeFunction(
                (vm, _) =>
            {
                var self   = ((SqHostObject)ScriptHandler.This).Object;
                var other  = ScriptHandler.GetArg <object>(0);
                var method = type.GetMethod("op_BitwiseOr", new Type[] { type, other.GetType() });
                if (method is null)
                {
                    throw new Exception($"Operator is not defined: {type.Name} | {other.GetType().Name}");
                }
                vm.PushDynamic(method.Invoke(null, new object[] { self, other }));
                return(1);
            }
                );
            del["BAnd"] = ScriptHandler.MakeFunction(
                (vm, _) =>
            {
                var self   = ((SqHostObject)ScriptHandler.This).Object;
                var other  = ScriptHandler.GetArg <object>(0);
                var method = type.GetMethod("op_BitwiseAnd", new Type[] { type, other.GetType() });
                if (method is null)
                {
                    throw new Exception($"Operator is not defined: {type.Name} & {other.GetType().Name}");
                }
                vm.PushDynamic(method.Invoke(null, new object[] { self, other }));
                return(1);
            }
                );
            del["Xor"] = ScriptHandler.MakeFunction(
                (vm, _) =>
            {
                var self   = ((SqHostObject)ScriptHandler.This).Object;
                var other  = ScriptHandler.GetArg <object>(0);
                var method = type.GetMethod("op_ExclusiveOr", new Type[] { type, other.GetType() });
                if (method is null)
                {
                    throw new Exception($"Operator is not defined: {type.Name} ^ {other.GetType().Name}");
                }
                vm.PushDynamic(method.Invoke(null, new object[] { self, other }));
                return(1);
            }
                );
            return(del);
        }
Example #6
0
        private static SqTable MakeProperties(Type type)
        {
            var props = new SqTable();

            // Convert type properties
            foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                var methods = new SqArray(2);
                props.Add(prop.Name, methods);
                // 0 = Property set method
                methods[0] = ScriptHandler.MakeFunction(
                    (_, __) =>
                {
                    var self      = (SqHostObject)ScriptHandler.This;
                    var setMethod = prop.GetSetMethod();
                    if (setMethod is null)
                    {
                        throw new Exception($"Cannot set property \"{self.Object.GetType()}.{prop.Name}\"");
                    }
                    var argType = prop.PropertyType;
                    var val     = ScriptHandler.GetArg(0, argType, true);
                    prop.GetSetMethod().Invoke(
                        (self).Object,
                        new object[] { val }
                        );
                    return(0);
                }
                    );
                // 1 = Property get method
                methods[1] = ScriptHandler.MakeFunction(
                    (vm, _) =>
                {
                    var self      = (SqHostObject)ScriptHandler.This;
                    var getMethod = prop.GetGetMethod();
                    if (getMethod is null)
                    {
                        throw new Exception($"Cannot get property \"{self.Object.GetType()}.{prop.Name}\"");
                    }
                    vm.PushDynamic(
                        getMethod.Invoke(
                            (self).Object,
                            null
                            )
                        );
                    return(1);
                }
                    );
            }
            // Convert type fields
            foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance))
            {
                var methods = new SqArray(2);
                props.Add(field.Name, methods);
                // 0 = Field set
                methods[0] = ScriptHandler.MakeFunction(
                    (_, __) =>
                {
                    var argType = field.FieldType;
                    var val     = ScriptHandler.GetArg(0, argType, true);
                    field.SetValue(((SqHostObject)ScriptHandler.This).Object, val);
                    return(0);
                }
                    );
                // 1 = Field get
                methods[1] = ScriptHandler.MakeFunction(
                    (vm, _) =>
                {
                    vm.PushDynamic(field.GetValue(((SqHostObject)ScriptHandler.This).Object));
                    return(1);
                }
                    );
            }
            return(props);
        }