protected bool CheckPrefix(string code) { if (Prefixes.Count > 0) { return(Prefixes.Any(p => code?.StartsWith(p) == true)); } return(true); }
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); }
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!"); } } }