Ejemplo n.º 1
0
        public override void Run()
        {
            var vanilla  = SourceDefinition.Type("Terraria.NPC").Method("StrikeNPC");
            var callback = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.Npc").Method("Strike");

            vanilla.InjectNonVoidBeginCallback(callback);
        }
Ejemplo n.º 2
0
        public override void Run()
        {
            var vanilla  = SourceDefinition.Type("Terraria.NPC").Method("NewNPC");
            var callback = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.Npc").Method("Create");


            var ctor = vanilla.Body.Instructions.Single(x => x.OpCode == OpCodes.Newobj &&
                                                        x.Operand is MethodReference &&
                                                        (x.Operand as MethodReference).DeclaringType.Name == "NPC");

            ctor.OpCode  = OpCodes.Call;
            ctor.Operand = vanilla.Module.Import(callback);

            //Remove <npc>.SetDefault() as we do something custom
            var remFrom = ctor.Next;
            var il      = vanilla.Body.GetILProcessor();

            while (remFrom.Next.Next.OpCode != OpCodes.Call)             //Remove until TypeToNum
            {
                il.Remove(remFrom.Next);
            }

            //            //Add Type to our callback
            //            il.InsertBefore(ctor, il.Create(OpCodes.Ldarg_2));

            il.InsertBefore(ctor, il.Create(OpCodes.Ldloca, vanilla.Body.Variables.First()));             //The first variable is the index
            for (var x = 0; x < vanilla.Parameters.Count; x++)
            {
                var opcode = callback.Parameters[x].ParameterType.IsByReference ? OpCodes.Ldarga : OpCodes.Ldarg;
                il.InsertBefore(ctor, il.Create(opcode, vanilla.Parameters[x]));
            }
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Constructor with endResidueLocInPeptide
 /// </summary>
 /// <param name="residue"></param>
 /// <param name="residueLocInPeptide"></param>
 /// <param name="residueTerminusState"></param>
 /// <param name="modDefinition"></param>
 /// <param name="endResidueLocInPeptide"></param>
 public AminoAcidModInfo(char residue, int residueLocInPeptide, ResidueTerminusState residueTerminusState, ModificationDefinition modDefinition, int endResidueLocInPeptide)
 {
     ModDefinition          = modDefinition;
     Residue                = residue;
     ResidueLocInPeptide    = residueLocInPeptide;
     EndResidueLocInPeptide = endResidueLocInPeptide;
     TerminusState          = residueTerminusState;
 }
Ejemplo n.º 4
0
        public override void Run()
        {
            var vanilla  = SourceDefinition.Type("Terraria.NetMessage").Method("SendData");
            var callback = vanilla.Module.Import(ModificationDefinition.Type("OTAPI.Callbacks.Terraria.NetMessage").Method("SendBytes"));

            //Hooking send bytes should be as simple as replacing each AsyncSend call with
            //the OTAPI callback as well as removing the socket instance and leaving the
            //remoteClient/num variable.
            //TODO: Netplay.Connection.Socket AsyncSend for client

            //Find all calls to AsyncSend
            var asyncSendCalls = vanilla.Body.Instructions.Where(x => x.OpCode == OpCodes.Callvirt &&
                                                                 x.Operand is MethodReference &&
                                                                 (x.Operand as MethodReference).Name == "AsyncSend" &&
                                                                 x.Previous(6).Operand is FieldReference &&
                                                                 (x.Previous(6).Operand as FieldReference).Name == "Clients")
                                 .ToArray();

            var il = vanilla.Body.GetILProcessor();

            foreach (var call in asyncSendCalls)
            {
                //Replace the call with our OTAPI callback
                call.OpCode  = OpCodes.Call;
                call.Operand = callback;

                //Wind back to the first Netplay.Clients (there are two, we want the one before the Socket reference)
                var clients = call.Previous(x => x.OpCode == OpCodes.Ldfld &&
                                            x.Operand is FieldReference &&
                                            (x.Operand as FieldReference).Name == "Socket")
                              .Previous(x => x.OpCode == OpCodes.Ldsfld &&
                                        x.Operand is FieldReference &&
                                        (x.Operand as FieldReference).Name == "Clients");

                //Remove the Socket call
                if (clients.Next.Next.OpCode != OpCodes.Ldelem_Ref)
                {
                    throw new InvalidOperationException($"{clients.Next.Next.OpCode} was not expected.");
                }
                il.Remove(clients.Next.Next);                 //ldelem.ref
                if (clients.Next.Next.OpCode != OpCodes.Ldfld)
                {
                    throw new InvalidOperationException($"{clients.Next.Next.OpCode} was not expected.");
                }
                il.Remove(clients.Next.Next);                 //ldfld

                //Remove the client call
                il.Remove(clients);
            }
        }
Ejemplo n.º 5
0
        public override void Run()
        {
            //Grab the Initialise method
            var vanilla = this.SourceDefinition.Type("Terraria.Main").Method("Initialize");

            var cbkBegin = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.Main").Method("InitializeBegin", parameters: vanilla.Parameters);
            var cbkEnd   = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.Main").Method("InitializeEnd", parameters: vanilla.Parameters);

            vanilla.Wrap
            (
                beginCallback: cbkBegin,
                endCallback: cbkEnd,
                beginIsCancellable: false,
                noEndHandling: false,
                allowCallbackInstance: true
            );
        }
Ejemplo n.º 6
0
        public override void Run()
        {
            var vanilla  = SourceDefinition.Type("Terraria.NetMessage").Method("SendData");
            var callback = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.NetMessage").Method("SendData");

            //Few stack issues arose trying to inject a callback before for lock, so i'll resort to
            //wrapping the method;

            vanilla.Wrap
            (
                beginCallback: callback,
                endCallback: null,
                beginIsCancellable: true,
                noEndHandling: false,
                allowCallbackInstance: false
            );
        }
Ejemplo n.º 7
0
        public override void Run()
        {
            var vanilla = SourceDefinition.Type("Terraria.Projectile").Methods.Single(
                x => x.Name == "AI" &&
                x.Parameters.Count() == 0
                );

            var cbkBegin = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.Projectile").Method("AIBegin", parameters: vanilla.Parameters);
            var cbkEnd   = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.Projectile").Method("AIEnd", parameters: vanilla.Parameters);

            vanilla.Wrap
            (
                beginCallback: cbkBegin,
                endCallback: cbkEnd,
                beginIsCancellable: true,
                noEndHandling: false,
                allowCallbackInstance: true
            );
        }
        public override void Run()
        {
            var vanilla = SourceDefinition.Type("Terraria.NPC").Methods.Single(
                x => x.Name == "SetDefaults" &&
                x.Parameters.First().ParameterType == SourceDefinition.MainModule.TypeSystem.String
                );

            var cbkBegin = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.Npc").Method("SetDefaultsByNameBegin", parameters: vanilla.Parameters);
            var cbkEnd   = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.Npc").Method("SetDefaultsByNameEnd", parameters: vanilla.Parameters);

            vanilla.Wrap
            (
                beginCallback: cbkBegin,
                endCallback: cbkEnd,
                beginIsCancellable: true,
                noEndHandling: false,
                allowCallbackInstance: true
            );
        }
Ejemplo n.º 9
0
        public override void Run()
        {
            foreach (var type in new[]
            {
                new { TypeDef = SourceDefinition.Type("Terraria.NPC"), MechType = OpCodes.Ldc_I4_1 },
                new { TypeDef = SourceDefinition.Type("Terraria.Item"), MechType = OpCodes.Ldc_I4_2 }
            })
            {
                var vanilla = type.TypeDef.Methods.Single(x => x.Name == "MechSpawn");
                var hook    = SourceDefinition.MainModule.Import(ModificationDefinition.Type("OTAPI.Callbacks.Terraria.World").Method("MechSpawn"));

                //Here we find the insertion point where we want to inject our callback at.
                var iInsertionPoint = vanilla.Body.Instructions.Last(x => x.OpCode == OpCodes.Ldloc_1);
                //If the result of the callback instructs us to cancel, this instruction will transfer us to the existing "return false"
                var iContinuePoint = vanilla.Body.Instructions.Last(x => x.OpCode == OpCodes.Ldc_I4_0);

                var il = vanilla.Body.GetILProcessor();

                //Add all the parameters
                foreach (var prm in vanilla.Parameters)
                {
                    il.InsertBefore(iInsertionPoint, il.Create(OpCodes.Ldarg, prm));
                }

                //Add the first three variables by reference
                for (var x = 0; x < 3; x++)
                {
                    il.InsertBefore(iInsertionPoint, il.Create(OpCodes.Ldloca, vanilla.Body.Variables[x]));
                }

                //Append our mech type enum value to the method call
                il.InsertBefore(iInsertionPoint, il.Create(type.MechType));

                //Trigger the method to run with the parameters on the stck
                il.InsertBefore(iInsertionPoint, il.Create(OpCodes.Call, hook));

                //If the result left on the stack is false, then jump to the "return false"
                il.InsertBefore(iInsertionPoint, il.Create(OpCodes.Brfalse_S, iContinuePoint));

                vanilla.Body.OptimizeMacros();
            }
        }
Ejemplo n.º 10
0
        public override void Run()
        {
            var vanilla = SourceDefinition.Type("Terraria.Projectile").Methods.Single(
                x => x.Name == "Update" &&
                x.Parameters.Single().ParameterType == SourceDefinition.MainModule.TypeSystem.Int32
                );


            var cbkBegin = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.Projectile").Method("UpdateBegin", parameters: vanilla.Parameters);
            var cbkEnd   = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.Projectile").Method("UpdateEnd", parameters: vanilla.Parameters);

            vanilla.Wrap
            (
                beginCallback: cbkBegin,
                endCallback: cbkEnd,
                beginIsCancellable: true,
                noEndHandling: false,
                allowCallbackInstance: true
            );
        }
Ejemplo n.º 11
0
        public override void Run()
        {
            var vanilla = SourceDefinition.Type("Terraria.IO.WorldFile").Methods.Single(
                x => x.Name == "loadWorld" &&
                x.Parameters.Count() == 1 &&
                x.Parameters[0].ParameterType == SourceDefinition.MainModule.TypeSystem.Boolean
                );

            var cbkBegin = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.WorldFile").Method("LoadWorldBegin", parameters: vanilla.Parameters);
            var cbkEnd   = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.WorldFile").Method("LoadWorldEnd", parameters: vanilla.Parameters);

            vanilla.Wrap
            (
                beginCallback: cbkBegin,
                endCallback: cbkEnd,
                beginIsCancellable: true,
                noEndHandling: false,
                allowCallbackInstance: false
            );
        }
Ejemplo n.º 12
0
        public override void Run()
        {
            var vanilla = SourceDefinition.Type("Terraria.NetMessage")
                          .Method("greetPlayer");

            var cbkBegin = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.NetMessage")
                           .Method("GreetPlayerBegin", parameters: vanilla.Parameters);

            var cbkEnd = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.NetMessage")
                         .Method("GreetPlayerEnd", parameters: vanilla.Parameters);

            vanilla.Wrap
            (
                beginCallback: cbkBegin,
                endCallback: cbkEnd,
                beginIsCancellable: true,
                noEndHandling: false,
                allowCallbackInstance: false
            );
        }
Ejemplo n.º 13
0
        public override void Run()
        {
            var vanilla  = SourceDefinition.Type("Terraria.NPC").Method("DropBossBags");
            var callback = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.Npc").Method("BossBagItem");

            var il = vanilla.Body.GetILProcessor();

            //Grad the NewItem calls
            var instructions = vanilla.Body.Instructions.Where(x => x.OpCode == OpCodes.Call &&
                                                               x.Operand is MethodReference &&
                                                               (x.Operand as MethodReference).Name == "NewItem" &&
                                                               x.Next.OpCode == OpCodes.Stloc_1);

            //Quick validation check
            if (instructions.Count() != 1)
            {
                throw new NotSupportedException("Only one server NewItem call expected in DropBossBags.");
            }

            //The first call is in the server block. TODO: client version
            var ins = instructions.First();

            //Swap the NewItem call to our custom item call
            ins.Operand = vanilla.Module.Import(callback);
            //Our argument appends the NPC instance (this) to the arguments
            il.InsertBefore(ins, il.Create(OpCodes.Ldarg_0));             //Instance methods ldarg.0 is the instance object

            //Now we start inserting our own if block to compare the call result.
            var target = ins.Next /*stloc.1*/.Next;                        //Grabs a reference to the instruction after the stloc.1 opcode so we can insert sequentially

            il.InsertBefore(target, il.Create(OpCodes.Ldloc_1));           //Load the num2 variable onto the stack
            il.InsertBefore(target, il.Create(OpCodes.Ldc_I4_M1));         //Load -1 onto the stack
            il.InsertBefore(target, il.Create(OpCodes.Ceq));               //Consume & compare the two variables and push 1 (true) or 0 (false) onto the stack
            il.InsertBefore(target, il.Create(OpCodes.Brfalse_S, target)); //if the output of ceq is 0 (false) then continue back on with the [target] instruction. In code terms, if the expression is not -1 then don't exit
            il.InsertBefore(target, il.Create(OpCodes.Ret));               //If we are here, the num2 variable is equal to -1, so we can exit the function.
        }
Ejemplo n.º 14
0
        public override void Run()
        {
            foreach (var newItem in SourceDefinition.Type("Terraria.Item").Methods.Where(
                         x => x.Name == "NewItem"
                         ))
            {
                //In this patch we create a custom DropLoot method that will be the receiver
                //of all Item.NewItem calls in NPCLoot.

                var typeNpc = this.Type <Terraria.NPC>();

                //Create the new DropLoot call in the Terraria.NPC class
                var dropLoot = new MethodDefinition("DropLoot", MethodAttributes.Public | MethodAttributes.Static, newItem.ReturnType);
                typeNpc.Methods.Add(dropLoot);

                dropLoot.Body.InitLocals = true;

                var il = dropLoot.Body.GetILProcessor();

                //Clone the parameters from the Item.NewItem method (with no byreference)
                foreach (var prm in newItem.Parameters)
                {
                    dropLoot.Parameters.Add(prm);
                }

                dropLoot.Parameters.Add(new ParameterDefinition(typeNpc)
                {
                    Name       = "npc",
                    IsOptional = true,
                    HasDefault = true,
                    Constant   = null
                });

                //Collect the hooks
                var cbkBegin = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.Npc").Method(
                    "DropLootBegin",
                    parameters: dropLoot.Parameters,
                    skipMethodParameters: 1,
                    substituteByRefs: true
                    );
                var cbkEnd = ModificationDefinition.Type("OTAPI.Callbacks.Terraria.Npc").Method(
                    "DropLootEnd",
                    parameters: dropLoot.Parameters,
                    skipMethodParameters: 0,
                    substituteByRefs: true
                    );

                //Create the value to hold the new item id
                var vrbItemId = new VariableDefinition("otaItem", (cbkBegin.Parameters[0].ParameterType as ByReferenceType).ElementType);
                dropLoot.Body.Variables.Add(vrbItemId);

                il.Emit(OpCodes.Ldloca_S, vrbItemId);                 //Loads our variable by reference so our callback and alter it.
                var beginResult = dropLoot.EmitBeginCallback(cbkBegin, false, false, false, parameterOffset: 1);

                //Inject the begin call
                var insFirstForMethod = dropLoot.EmitMethodCallback(newItem, false, false);
                //Store the result into our new variable
                il.Emit(OpCodes.Stloc, vrbItemId);

                //Set the vanilla instruction to be resumed upon continuation of the begin hook.
                if (beginResult != null && beginResult.OpCode == OpCodes.Pop)
                {
                    beginResult.OpCode  = OpCodes.Brtrue_S;
                    beginResult.Operand = insFirstForMethod;

                    //Emit the cancellation return IL
                    il.InsertAfter(beginResult, il.Create(OpCodes.Ret));
                    il.InsertAfter(beginResult, il.Create(OpCodes.Ldloc, vrbItemId));
                }

                //Inject the end callback
                dropLoot.EmitEndCallback(cbkEnd, false, false);

                //Emit the return value using the result variable we injected
                il.Emit(OpCodes.Ldloc, vrbItemId);
                il.Emit(OpCodes.Ret);
            }
        }
Ejemplo n.º 15
0
        private bool ReadModSummaryFile(string modSummaryFilePath)
        {
            ModificationDefs.Clear();

            if (string.IsNullOrEmpty(modSummaryFilePath))
            {
                return(false);
            }

            // Initialize the column mapping
            // Using a case-insensitive comparer
            var columnHeaders = new SortedDictionary <string, int>(StringComparer.OrdinalIgnoreCase)
            {
                { MOD_SUMMARY_COLUMN_Modification_Symbol, 0 },
                { MOD_SUMMARY_COLUMN_Modification_Mass, 1 },
                { MOD_SUMMARY_COLUMN_Target_Residues, 2 },
                { MOD_SUMMARY_COLUMN_Modification_Type, 3 },
                { MOD_SUMMARY_COLUMN_Mass_Correction_Tag, 4 },
                { MOD_SUMMARY_COLUMN_Occurrence_Count, 5 }
            };

            // Read the data from the ModSummary.txt file
            // The first line is typically a header line:
            // Modification_Symbol  Modification_Mass  Target_Residues  Modification_Type  Mass_Correction_Tag  Occurrence_Count

            using var modSummaryReader = new StreamReader(new FileStream(modSummaryFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));

            var headerLineParsed = false;

            while (!modSummaryReader.EndOfStream)
            {
                var lineIn   = modSummaryReader.ReadLine();
                var skipLine = false;

                if (string.IsNullOrEmpty(lineIn))
                {
                    continue;
                }

                var splitLine = lineIn.Split('\t');

                if (!headerLineParsed)
                {
                    if (string.Equals(splitLine[0], MOD_SUMMARY_COLUMN_Modification_Symbol, StringComparison.OrdinalIgnoreCase))
                    {
                        // Parse the header line to confirm the column ordering
                        // The Occurrence_Count column was misspelled prior to December 2012; need to check for this
                        for (var index = 0; index <= splitLine.Length - 1; index++)
                        {
                            // ReSharper disable once StringLiteralTypo
                            if (splitLine[index] != "Occurence_Count")
                            {
                                continue;
                            }

                            splitLine[index] = MOD_SUMMARY_COLUMN_Occurrence_Count;
                            break;
                        }

                        ReaderFactory.ParseColumnHeaders(splitLine, columnHeaders);
                        skipLine = true;
                    }

                    headerLineParsed = true;
                }

                if (skipLine || splitLine.Length < 4)
                {
                    continue;
                }

                var modSymbolText     = ReaderFactory.LookupColumnValue(splitLine, MOD_SUMMARY_COLUMN_Modification_Symbol, columnHeaders);
                var modMassText       = ReaderFactory.LookupColumnValue(splitLine, MOD_SUMMARY_COLUMN_Modification_Mass, columnHeaders);
                var targetResidues    = ReaderFactory.LookupColumnValue(splitLine, MOD_SUMMARY_COLUMN_Target_Residues, columnHeaders);
                var modType           = ReaderFactory.LookupColumnValue(splitLine, MOD_SUMMARY_COLUMN_Modification_Type, columnHeaders);
                var massCorrectionTag = ReaderFactory.LookupColumnValue(splitLine, MOD_SUMMARY_COLUMN_Mass_Correction_Tag, columnHeaders);

                if (string.IsNullOrWhiteSpace(modSymbolText))
                {
                    modSymbolText = ModificationDefinition.NO_SYMBOL_MODIFICATION_SYMBOL.ToString();
                }

                var modSymbol = modSymbolText[0];

                if (!double.TryParse(modMassText, out var modificationMass))
                {
                    throw new Exception("Modification mass is not numeric for MassCorrectionTag: " + massCorrectionTag + ": " + modMassText);
                }

                ModificationDefinition.ResidueModificationType modificationType;
                if (string.IsNullOrWhiteSpace(modType))
                {
                    modificationType = ModificationDefinition.ResidueModificationType.UnknownType;
                }
                else
                {
                    modificationType = ModificationDefinition.ModificationSymbolToModificationType(modType[0]);
                }

                var modDef =
                    new ModificationDefinition(modSymbol, modificationMass, targetResidues, modificationType, massCorrectionTag)
                {
                    ModificationMassAsText = modMassText
                };

                ModificationDefs.Add(modDef);

                if (!mModDefMassesAsText.ContainsKey(massCorrectionTag))
                {
                    mModDefMassesAsText.Add(massCorrectionTag, modMassText);
                }
            }

            return(true);
        }
 /// <summary>
 /// Returns the TypeDefintion of the type specified
 /// </summary>
 public TypeDefinition Type <T>() => ModificationDefinition.Type <T>();