Esempio n. 1
0
        public TargetInstruction[] BasicInformation(MethodDef method)
        {
            var insts = new TargetInstruction[2];

            foreach (var instruction in method.Body.Instructions.Where(
                         i => i.Operand is IMethodDefOrRef m &&
                         m.IsMethod(nameof(ModTranslation), nameof(ModTranslation.SetDefault))))
            {
                var source = method.Body.FindObjectInstance(instruction);
                var value  = method.Body.FindStringLiteralBefore(instruction);
                if (source == null || value == null)
                {
                    continue;
                }

                // some mod may have custom translation here
                // source will be ldloc.x
                if (((IMethodDefOrRef)source.Operand)?.Name?.ToString() == null)
                {
                    continue;
                }

                switch (((IMethodDefOrRef)source.Operand).Name)
                {
                case "get_Tooltip":
                    insts[1] = new TargetInstruction
                    {
                        ReplaceTarget = source,
                        Value         = value
                    };
                    break;

                case "get_DisplayName":
                    insts[0] = new TargetInstruction
                    {
                        ReplaceTarget = source,
                        Value         = value
                    };
                    break;
                }
            }

            return(insts);
        }
Esempio n. 2
0
        public TargetInstruction[] SetDefault(MethodDef method)
        {
            var targets = new TargetInstruction[2];

            foreach (var instruction in method.Body.Instructions.Where(
                         i => i.Operand is IMethodDefOrRef m &&
                         m.IsMethod(nameof(ModTranslation), nameof(ModTranslation.SetDefault))))
            {
                var source = method.Body.FindObjectInstance(instruction);
                var value  = method.Body.FindStringLiteralBefore(instruction);
                if (source == null || value == null)
                {
                    continue;
                }

                switch (((IMethodDefOrRef)source.Operand).Name)
                {
                case "get_DisplayName":
                    targets[0] = new TargetInstruction
                    {
                        ReplaceTarget = source,
                        Value         = value
                    };
                    break;

                case "get_Description":
                    targets[1] = new TargetInstruction
                    {
                        ReplaceTarget = source,
                        Value         = value
                    };
                    break;
                }
            }

            return(targets);
        }
Esempio n. 3
0
        public TargetInstruction[] ChatButton(MethodDef method)
        {
            var targets = new TargetInstruction[2];

            var instructions = method.Body.Instructions;

            for (var index = 0; index < instructions.Count; index++)
            {
                var ldstr = instructions[index];

                if (ldstr.OpCode != OpCodes.Ldstr)
                {
                    continue;
                }

                // arg_1: shop button 1
                // arg_2: shop button 2
                // value is assigned to the byRef parameter
                var ldarg = instructions.ElementAtOrDefault(index - 1);
                if (ldarg == null)
                {
                    continue;
                }

                if (ldarg.OpCode.Equals(OpCodes.Ldarg_1))
                {
                    targets[0] = new TargetInstruction(ldstr);
                }
                else if (ldarg.OpCode.Equals(OpCodes.Ldarg_2))
                {
                    targets[1] = new TargetInstruction(ldstr);
                }
            }

            return(targets);
        }
        public override KeyValuePair <string, Expression>?GetExpression <TSource>(Type outerSourceType, ParameterExpression rootParameter, IEnumerable <TSource> source)
        {
            if (outerSourceType == null)
            {
                throw new ArgumentNullException(nameof(outerSourceType));
            }

            // 1. Split the value & extract the field names or requests.
            var splitted     = Parameter.Split(',');
            var instructions = splitted.Select(s => InstructionHelper.ExtractInstruction(s)).Where(s => s.HasValue);

            if (!parameters.Any(p => instructions.Any(i => i.Value.Key == p)))
            {
                throw new ArgumentException("either inner or outer parameter is not specified");
            }

            // 2. Construct the expressions.
            var outer       = instructions.First(i => i.Value.Key == outerKey).Value.Value;
            var inner       = instructions.First(i => i.Value.Key == innerKey).Value.Value;
            var select      = instructions.FirstOrDefault(i => i.Value.Key == selectKey);
            var selectValue = string.Empty;

            if (select != null)
            {
                selectValue = select.Value.Value;
            }

            Type       innerSourceType  = outerSourceType;
            Expression targetExpression = null;

            if (TargetInstruction != null)
            {
                var targetArg = Expression.Parameter(typeof(IQueryable <TSource>), "t");
                targetExpression = TargetInstruction.GetExpression(outerSourceType, targetArg, source).Value.Value;
                innerSourceType  = targetExpression.Type.GetGenericArguments().First();
            }

            Type             tResult     = innerSourceType;
            var              fieldNames  = outer.GetParameters();
            var              outerArg    = Expression.Parameter(outerSourceType, "x");
            var              innerArg    = Expression.Parameter(innerSourceType, "y");
            LambdaExpression outerLambda = null,
                             innerLambda = null;
            Type resultType;

            if (fieldNames.Count() == 1)
            {
                resultType = outerSourceType.GetProperty(fieldNames.First()).PropertyType;
                var outerProperty = Expression.Property(outerArg, fieldNames.First());
                var innerProperty = Expression.Property(innerArg, fieldNames.First());
                outerLambda = Expression.Lambda(outerProperty, new ParameterExpression[] { outerArg });
                innerLambda = Expression.Lambda(innerProperty, new ParameterExpression[] { innerArg });
            }
            else
            {
                var commonAnonType = ReflectionHelper.CreateNewAnonymousType(outerSourceType, fieldNames);
                resultType = commonAnonType.AsType();
                var outerNewExpr = ExpressionBuilder.BuildNew(outer, outerSourceType, commonAnonType, outerArg);
                var innerNewExpr = ExpressionBuilder.BuildNew(inner, innerSourceType, commonAnonType, innerArg);
                outerLambda = Expression.Lambda(outerNewExpr, new ParameterExpression[] { outerArg });
                innerLambda = Expression.Lambda(innerNewExpr, new ParameterExpression[] { innerArg });
            }

            LambdaExpression selectorResult = null;

            if (string.IsNullOrWhiteSpace(selectValue))
            {
                selectorResult = Expression.Lambda(outerArg, new ParameterExpression[] { outerArg, innerArg });
            }
            else
            {
                var selectAttributes = new List <KeyValuePair <string, ICollection <string> > >();
                foreach (var val in selectValue.Split('|'))
                {
                    var values = val.Split('$');
                    if (values.Count() != 2 && values.Count() != 1)
                    {
                        continue;
                    }

                    var key = values.First();
                    var kvp = selectAttributes.FirstOrDefault(s => s.Key == key);
                    if (kvp.IsEmpty())
                    {
                        kvp = new KeyValuePair <string, ICollection <string> >(key, new List <string>());
                        selectAttributes.Add(kvp);
                    }

                    if (values.Count() == 2)
                    {
                        kvp.Value.Add(values.ElementAt(1));
                    }
                }

                if (!selectAttributes.Any(a => selectParameters.Contains(a.Key)))
                {
                    throw new InvalidOperationException("At least one parameter in select is not supported");
                }

                Dictionary <string, Type> mapping = new Dictionary <string, Type>();
                var outerSelect = selectAttributes.FirstOrDefault(a => a.Key == outerKey);
                var innerSelect = selectAttributes.FirstOrDefault(a => a.Key == innerKey);
                AddTypes(mapping, "outer", outerSourceType, outerSelect);
                AddTypes(mapping, "inner", innerSourceType, innerSelect);
                var anonymousType = ReflectionHelper.CreateNewAnonymousType(mapping);
                var parameters    = new List <Expression>();
                var tmp           = GetParameterExpressions(outerArg, outerSelect);
                if (tmp != null)
                {
                    parameters.AddRange(tmp);
                }

                tmp = GetParameterExpressions(innerArg, innerSelect);
                if (tmp != null)
                {
                    parameters.AddRange(tmp);
                }

                var newExpr = Expression.New(anonymousType.DeclaredConstructors.First(), parameters);
                selectorResult = Expression.Lambda(newExpr, new ParameterExpression[] { innerArg, outerArg });
                tResult        = anonymousType.AsType();
            }

            var enumarableType        = typeof(Queryable);
            var method                = enumarableType.GetMethods().Where(m => m.Name == "Join" && m.IsGenericMethodDefinition).Where(m => m.GetParameters().ToList().Count == 5).First();
            var genericMethod         = method.MakeGenericMethod(outerSourceType, innerSourceType, resultType, tResult);
            MethodCallExpression call = null;

            if (targetExpression == null)
            {
                call = Expression.Call(genericMethod, Expression.Constant(source), Expression.Constant(source), outerLambda, innerLambda, selectorResult);
            }
            else
            {
                call = Expression.Call(genericMethod, Expression.Constant(source), targetExpression, Expression.Constant(outerLambda), Expression.Constant(innerLambda), selectorResult);
            }

            return(new KeyValuePair <string, Expression>(Name, call));
        }
Esempio n. 5
0
        protected void SetAssignmentTarget(TargetInstruction instruction)
        {
            if (_currentAssignmentTarget != null)
            {
                throw new FormatException("Assignment target already set");
            }
            switch (instruction.Target)
            {
            // special strings
            case DataElement.SStr sstr:
                _currentAssignmentTarget = new AssignmentTarget.SpecialString(sstr.FlagType.StringValue);
                break;



            // integer variable pointers
            case DataElement.VInt vint when vint.FlagId.IsPointer:
                _currentAssignmentTarget = new AssignmentTarget.VariablePointer(vint.FlagType.StringValue, vint.FlagId.PointerId);
                break;



            // integer variables
            case DataElement.VInt vint:
                // range checks
                if (vint.FlagId.IntValue < 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(vint.FlagId.IntValue), vint.FlagId.IntValue, "Flag index must be positive");
                }
                if (vint.FlagId.IntValue >= GlobalFlagTableSize && vint.FlagType.StringValue == YksFormat.GlobalFlag)
                {
                    throw new ArgumentOutOfRangeException(nameof(vint.FlagId.IntValue), vint.FlagId.IntValue, "Global flag index must be smaller than " + GlobalFlagTableSize);
                }
                if (vint.FlagId.IntValue >= LocalFlagTableSize && vint.FlagType.StringValue == YksFormat.Flag)
                {
                    throw new ArgumentOutOfRangeException(nameof(vint.FlagId.IntValue), vint.FlagId.IntValue, "Local flag index must be smaller than " + LocalFlagTableSize);
                }

                _currentAssignmentTarget = new AssignmentTarget.Variable(vint.FlagType.StringValue, vint.FlagId.IntValue);
                break;



            // string variable pointers
            case DataElement.VStr vstr when vstr.FlagId.IsPointer:
                _currentAssignmentTarget = new AssignmentTarget.VariablePointer(vstr.FlagType.StringValue, vstr.FlagId.PointerId);
                break;



            // integer variables
            case DataElement.VStr vstr:
                // range checks
                if (vstr.FlagId.IntValue < 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(vstr.FlagId.IntValue), vstr.FlagId.IntValue, "String index must be positive");
                }
                if (vstr.FlagId.IntValue >= GlobalStringTableSize && vstr.FlagType.StringValue == YksFormat.GlobalString)
                {
                    throw new ArgumentOutOfRangeException(nameof(vstr.FlagId.IntValue), vstr.FlagId.IntValue, "String flag index must be smaller than " + GlobalStringTableSize);
                }
                if (vstr.FlagId.IntValue >= LocalStringTableSize && vstr.FlagType.StringValue == YksFormat.String)
                {
                    throw new ArgumentOutOfRangeException(nameof(vstr.FlagId.IntValue), vstr.FlagId.IntValue, "String flag index must be smaller than " + LocalStringTableSize);
                }

                _currentAssignmentTarget = new AssignmentTarget.Variable(vstr.FlagType.StringValue, vstr.FlagId.IntValue);
                break;



            // local variables
            case DataElement.VLoc vloc:
                if (vloc.Id >= Script.InstructionList.MaxLocals)
                {
                    throw new ArgumentOutOfRangeException(nameof(vloc.Id), vloc.Id, "Local variable id must be smaller than local variable pool size (" + Script.InstructionList.MaxLocals + ")");
                }
                _currentAssignmentTarget = new AssignmentTarget.Local(vloc.Id);
                break;



            // int pointers
            case DataElement.CInt cint:
                cint.Value.PointerId     = _flagPointerId++;
                _currentAssignmentTarget = new AssignmentTarget.IntPointer(cint.Value.PointerId);
                break;



            default:
                throw new ArgumentOutOfRangeException(nameof(instruction), "Invalid assignment target: " + instruction);
            }
        }