Example #1
0
 protected bool CheckPrefix(string code)
 {
     if (Prefixes.Count > 0)
     {
         return(Prefixes.Any(p => code?.StartsWith(p) == true));
     }
     return(true);
 }
Example #2
0
        private IEnumerable <MsilInstruction> EmitPatched(Func <Type, bool, MsilLocal> declareLocal)
        {
            var methodBody = _method.GetMethodBody();

            Debug.Assert(methodBody != null, "Method body is null");
            foreach (var localVar in methodBody.LocalVariables)
            {
                Debug.Assert(localVar.LocalType != null);
                declareLocal(localVar.LocalType, localVar.IsPinned);
            }

            var instructions     = new List <MsilInstruction>();
            var specialVariables = new Dictionary <string, MsilLocal>();

            var labelAfterOriginalContent = new MsilLabel();
            var labelSkipMethodContent    = new MsilLabel();


            Type      returnType     = _method is MethodInfo meth ? meth.ReturnType : typeof(void);
            MsilLocal resultVariable = null;

            if (returnType != typeof(void))
            {
                if (Prefixes.Concat(Suffixes).SelectMany(x => x.GetParameters()).Any(x => x.Name == RESULT_PARAMETER) ||
                    Prefixes.Any(x => x.ReturnType == typeof(bool)))
                {
                    resultVariable = declareLocal(returnType, false);
                }
            }

            if (resultVariable != null)
            {
                instructions.AddRange(resultVariable.SetToDefault());
            }
            MsilLocal prefixSkippedVariable = null;

            if (Prefixes.Count > 0 && Suffixes.Any(x => x.GetParameters()
                                                   .Any(y => y.Name.Equals(PREFIX_SKIPPED_PARAMETER))))
            {
                prefixSkippedVariable = declareLocal(typeof(bool), false);
                specialVariables.Add(PREFIX_SKIPPED_PARAMETER, prefixSkippedVariable);
            }

            if (resultVariable != null)
            {
                specialVariables.Add(RESULT_PARAMETER, resultVariable);
            }

            // Create special variables
            foreach (var m in Prefixes.Concat(Suffixes))
            {
                foreach (var param in m.GetParameters())
                {
                    if (param.Name.StartsWith(LOCAL_PARAMETER))
                    {
                        var requiredType = param.ParameterType.IsByRef ? param.ParameterType.GetElementType() : param.ParameterType;
                        if (specialVariables.TryGetValue(param.Name, out var existingParam))
                        {
                            if (existingParam.Type != requiredType)
                            {
                                throw new ArgumentException(
                                          $"Trying to use injected local {param.Name} for {m.DeclaringType?.FullName}#{m.ToString()} with type {requiredType} but a local with the same name already exists with type {existingParam.Type}",
                                          param.Name);
                            }
                        }
                        else
                        {
                            specialVariables.Add(param.Name, declareLocal(requiredType, false));
                        }
                    }
                }
            }

            foreach (MethodInfo prefix in Prefixes)
            {
                instructions.AddRange(EmitMonkeyCall(prefix, specialVariables));
                if (prefix.ReturnType == typeof(bool))
                {
                    instructions.Add(new MsilInstruction(OpCodes.Brfalse).InlineTarget(labelSkipMethodContent));
                }
                else if (prefix.ReturnType != typeof(void))
                {
                    throw new Exception(
                              $"Prefixes must return void or bool.  {prefix.DeclaringType?.FullName}.{prefix.Name} returns {prefix.ReturnType}");
                }
            }

            instructions.AddRange(MethodTranspiler.Transpile(_method, (x) => declareLocal(x, false), Transpilers, labelAfterOriginalContent));

            instructions.Add(new MsilInstruction(OpCodes.Nop).LabelWith(labelAfterOriginalContent));
            if (resultVariable != null)
            {
                instructions.Add(new MsilInstruction(OpCodes.Stloc).InlineValue(resultVariable));
            }
            var notSkip = new MsilLabel();

            instructions.Add(new MsilInstruction(OpCodes.Br).InlineTarget(notSkip));
            instructions.Add(new MsilInstruction(OpCodes.Nop).LabelWith(labelSkipMethodContent));
            if (prefixSkippedVariable != null)
            {
                instructions.Add(new MsilInstruction(OpCodes.Ldc_I4_1));
                instructions.Add(new MsilInstruction(OpCodes.Stloc).InlineValue(prefixSkippedVariable));
            }

            instructions.Add(new MsilInstruction(OpCodes.Nop).LabelWith(notSkip));

            foreach (MethodInfo suffix in Suffixes)
            {
                instructions.AddRange(EmitMonkeyCall(suffix, specialVariables));
                if (suffix.ReturnType != typeof(void))
                {
                    throw new Exception($"Suffixes must return void.  {suffix.DeclaringType?.FullName}.{suffix.Name} returns {suffix.ReturnType}");
                }
            }

            if (resultVariable != null)
            {
                instructions.Add(new MsilInstruction(OpCodes.Ldloc).InlineValue(resultVariable));
            }
            instructions.Add(new MsilInstruction(OpCodes.Ret));

            var result = MethodTranspiler.Transpile(_method, instructions, (x) => declareLocal(x, false), PostTranspilers, null).ToList();

            if (result.Last().OpCode != OpCodes.Ret)
            {
                result.Add(new MsilInstruction(OpCodes.Ret));
            }
            return(result);
        }
Example #3
0
        public static void ManagePrefixGroups(CommandArgs args)
        {
            bool Add = args.Parameters[0].ToLower() == "add";

            if (Add)
            {
                if (args.Parameters.Count < 5)
                {
                    args.Player.SendErrorMessage(TShock.Config.CommandSpecifier + "bprefix add group [Name] [Permission] [AllowedPrefixes (1 3 10...)]");
                    return;
                }
                string Name = args.Parameters[2];
                if (Prefixes.Any(b => b.Name == Name))
                {
                    args.Player.SendErrorMessage("Prefix group with '{0}' name already exists.", Name);
                    return;
                }
                string     Permission      = args.Parameters[3];
                List <int> AllowedPrefixes = new List <int>();
                for (int i = 4; i < args.Parameters.Count; i++)
                {
                    if (!int.TryParse(args.Parameters[i], out int PrefixID) ||
                        (PrefixID < 0) || (PrefixID > (Lang.prefix.Length - 1)))
                    {
                        args.Player.SendErrorMessage("Invalid PrefixID '{0}'!", args.Parameters[i]);
                        continue;
                    }
                    AllowedPrefixes.Add(PrefixID);
                }

                var BTP = new BTPrefix(Name, Permission, AllowedPrefixes);
                Prefixes.Add(BTP);
                BTDatabase.PAdd(BTP);
                args.Player.SendSuccessMessage("Successfully added new prefix group with given name: {0}.", Name);
            }
            else
            {
                if (args.Parameters.Count != 3)
                {
                    args.Player.SendErrorMessage(TShock.Config.CommandSpecifier + "bprefix del group [Name]");
                    return;
                }
                string Name    = args.Parameters[2];
                bool   Success = false;
                foreach (var p in Prefixes)
                {
                    if (p.Name == Name)
                    {
                        Success = true;
                        Prefixes.Remove(p);
                        break;
                    }
                }
                if (Success)
                {
                    args.Player.SendSuccessMessage("Successfully deleted prefix group with given name: {0}.", Name);
                    BTDatabase.PDelete(Name);
                }
                else
                {
                    args.Player.SendErrorMessage("Invalid PrefixGroup name!");
                }
            }
        }