Ejemplo n.º 1
0
        public override void Run()
        {
            var vanilla          = SourceDefinition.Type("Terraria.NPC").Method("NewNPC");
            int tmp              = 0;
            var callback         = this.Method(() => OTAPI.Callbacks.Terraria.Npc.Spawn(ref tmp));
            var importedCallback = SourceDefinition.MainModule.Import(callback);

            //This hook is to notify when a npc has been created, and is about to be spawned into
            //the world.
            //What we do is look in Terraria.NPC.NewNPC for the following code:
            //      Main.npc[num].target = Target;
            //      if (Type == 50)
            //
            //Between these two lines we inject a cancelable callback:
            //      Main.npc[num].target = Target;
            //      if(!OTAPI.Callbacks.Terraria.Npc.Spawn(ref num))
            //      {
            //          return index;
            //      }
            //      if (Type == 50)

            //Find the `if (Type == 50) offset instruction so we can use it
            //as our insertion point
            var insInsertionPoint = vanilla.Body.Instructions.Single(i =>
                                                                     i.OpCode == OpCodes.Ldarg_2 &&
                                                                     i.Next.OpCode == OpCodes.Ldc_I4_S &&
                                                                     i.Next.Operand.Equals((sbyte)50) &&
                                                                     i.Next.Next.OpCode == OpCodes.Bne_Un_S
                                                                     );

            //Get the il processor so we can alter il
            var processor = vanilla.Body.GetILProcessor();

            //Find the npc index, using the only ret instruction that doesn't
            //have an operand
            var insNpcIndex = vanilla.Body.Instructions.Single(i =>
                                                               i.OpCode == OpCodes.Ret &&
                                                               i.Previous != null &&
                                                               i.Previous.Operand == null
                                                               );

            //Expect ldloc.0 (as we will use it by reference later)
            if (insNpcIndex.Previous.OpCode != OpCodes.Ldloc_0)
            {
                throw new NotImplementedException($"Expected ldloc.0 rather than {insNpcIndex.Previous.OpCode}");
            }

            //Inject out callback il
            processor.InsertBefore(insInsertionPoint,
                                   //Load the npc index by reference
                                   new { OpCodes.Ldloca, Operand = vanilla.Body.Variables.First() },
                                   //Invoke our callback using the npc index that is on the stack as a reference
                                   new { OpCodes.Call, importedCallback },
                                   //If the callback returns true, then continue back to vanilla
                                   new { OpCodes.Brtrue_S, insInsertionPoint },
                                   //Otherwise, if false then return the modified npc index
                                   new { OpCodes.Ldloc_0 },
                                   new { OpCodes.Ret }
                                   );
        }
Ejemplo n.º 2
0
        public override void Run()
        {
            var vanilla = SourceDefinition.Type("Terraria.Player")
                          .Method("KillMe");

            double tmp      = 0;
            int    tmp1     = 0;
            bool   tmp2     = false;
            string tmp3     = null;
            var    cbkBegin = this.SourceDefinition.MainModule.Import(
                this.Method(() => OTAPI.Callbacks.Terraria.Player.KillMeBegin(null, ref tmp, ref tmp1, ref tmp2, ref tmp3))
                );

            var cbkEnd = this.SourceDefinition.MainModule.Import(
                this.Method(() => OTAPI.Callbacks.Terraria.Player.KillMeEnd(null, 0, 0, false, null))
                );

            vanilla.Wrap
            (
                beginCallback: cbkBegin,
                endCallback: cbkEnd,
                beginIsCancellable: true,
                noEndHandling: false,
                allowCallbackInstance: true
            );
        }
Ejemplo n.º 3
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.º 4
0
        public override void Run()
        {
            var vanilla = SourceDefinition.Type("Terraria.Player")
                          .Method("LoadPlayer");

            string tmp  = null;
            bool   tmp2 = false;

            global::Terraria.IO.PlayerFileData data = null;
            var cbkBegin =             //this.SourceDefinition.MainModule.Import(
                           this.Method(() => OTAPI.Callbacks.Terraria.Player.LoadBegin(ref data, ref tmp, ref tmp2));

            //);

            //var cbkEnd = this.SourceDefinition.MainModule.Import(
            //	this.Method(() => OTAPI.Callbacks.Terraria.Player.LoadEnd(null, false))
            //);

            vanilla.InjectNonVoidBeginCallback(cbkBegin);
            //vanilla.Wrap
            //(
            //	beginCallback: cbkBegin,
            //	endCallback: cbkEnd,
            //	beginIsCancellable: true,
            //	noEndHandling: false,
            //	allowCallbackInstance: false,
            //	overrideReturnType: vanilla.ReturnType
            //);
        }
Ejemplo n.º 5
0
        public override void Run()
        {
            var npcLoot  = SourceDefinition.Type("Terraria.NPC").Method("NPCLoot");
            var dropLoot = SourceDefinition.Type("Terraria.NPC").Method("DropLoot");

            //In the NPCLoot method there is a call to send packet 88 (after item drop).
            //We will also want to hook this in the case the returned value from DropLoot
            //cancels the event.
            //Note, each update will need checking for any other calls to DropLoot that populate variables
            //as currently this is the only one.
            //TODO: write a test for this

            var il = npcLoot.Body.GetILProcessor();

            //This section will add '&& num40 >= 0' to the statement above "Main.item [num40].color = this.color;"
            var insColour         = npcLoot.Body.Instructions.Single(x => x.OpCode == OpCodes.Ldfld && x.Operand == SourceDefinition.Type("Terraria.NPC").Field("color")); //Grab where the call is located
            var insColorStart     = insColour.Previous(i => i.OpCode == OpCodes.Ldsfld);                                                                                   //Find the first instruction for the color call
            var resumeInstruction = insColorStart.Previous.Operand as Instruction;                                                                                         //Find the instruction where it should be transferred to if false is evaludated

            il = npcLoot.Body.GetILProcessor();

            //Insert the num40 variable (the result back from the DropLoot method)
            il.InsertBefore(insColorStart, il.Create(OpCodes.Ldloc, (VariableDefinition)insColorStart.Next.Operand));
            //Place 0 on the stack
            il.InsertBefore(insColorStart, il.Create(OpCodes.Ldc_I4_0));
            //Compare the current values on stack, using >=
            il.InsertBefore(insColorStart, il.Create(OpCodes.Blt, resumeInstruction));

            npcLoot.Body.OptimizeMacros();
        }
Ejemplo n.º 6
0
        void AddSource(string link)
        {
            try
            {
                var uri = new Uri(link).ToString();
                if (uri[uri.Length - 1] != '/')
                {
                    uri = uri + '/';
                }

                foreach (var src in Sources)
                {
                    if (uri == src.ToString())
                    {
                        MessageBox.Show("The given URI is already exist.", "Can't add source",
                                        MessageBoxButton.OK, MessageBoxImage.Warning);
                        return;
                    }
                }

                var sd = new SourceDefinition(uri);
                Sources.Add(sd);
                sd.ApplySources(Sources);
                wapkg.PushSources(Sources);
            }

            catch (UriFormatException)
            {
                MessageBox.Show("Invalid URI.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
Ejemplo n.º 7
0
 /// <summary>
 /// Abstract base class for joins of two source definitions.
 /// </summary>
 /// <param name="Left">Left source definition.</param>
 /// <param name="Right">Right source definition.</param>
 /// <param name="Conditions">Join conditions.</param>
 /// <param name="Start">Start position in script expression.</param>
 /// <param name="Length">Length of expression covered by node.</param>
 /// <param name="Expression">Expression containing script.</param>
 public Join(SourceDefinition Left, SourceDefinition Right, ScriptNode Conditions, int Start, int Length, Expression Expression)
     : base(Start, Length, Expression)
 {
     this.left       = Left;
     this.right      = Right;
     this.conditions = Conditions;
 }
Ejemplo n.º 8
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.º 9
0
        public override void Run()
        {
            var npcLoot  = SourceDefinition.Type("Terraria.NPC").Method("NPCLoot");
            var dropLoot = SourceDefinition.Type("Terraria.NPC").Method("DropLoot");

            //In this patch we swap all Item.NewItem calls in NPCLoot to use our previously
            //created DropLoot method

            //Gather all Item.NewItem calls
            var itemCalls = npcLoot.Body.Instructions.Where(x => x.OpCode == OpCodes.Call &&
                                                            x.Operand is MethodReference &&
                                                            (x.Operand as MethodReference).Name == "NewItem" &&
                                                            (x.Operand as MethodReference).DeclaringType.Name == "Item").ToArray();

            var processor = npcLoot.Body.GetILProcessor();

            //Swap each Item.NewItem calls to our Npc.DropLoot method.
            foreach (var call in itemCalls)
            {
                //Swap to our custom method
                call.Operand = dropLoot;

                //Append the additional arguments to the end of the existing call
                processor.InsertBefore(call, new[]
                {
                    new { OpCodes.Ldarg_0 }                     //Adds 'this' (so the npc instance)
                });
            }

            //Ensure the short branches are updated
            npcLoot.Body.SimplifyMacros();
            npcLoot.Body.OptimizeMacros();
        }
Ejemplo n.º 10
0
        public override void Run()
        {
            //Get the vanilla meteor method reference
            var vanilla = SourceDefinition.Type("Terraria.WorldGen").Method("meteor");

            //Get the OTAPI callback method reference
            int tmp      = 0;
            var callback = this.SourceDefinition.MainModule.Import(
                this.Method(() => OTAPI.Callbacks.Terraria.WorldGen.DropMeteor(ref tmp, ref tmp))
                );

            //Look for stopDrops = true in the vanilla methods instructions
            var stopDrops = vanilla.Body.Instructions.Single(instruction =>
                                                             instruction.OpCode == OpCodes.Stsfld &&
                                                             instruction.Operand is FieldReference &&
                                                             (instruction.Operand as FieldReference).Name == "stopDrops"

                                                             && instruction.Previous.OpCode == OpCodes.Ldc_I4_1
                                                             );

            //Get the IL processor instance so we can inject some il
            var processor = vanilla.Body.GetILProcessor();

            //Get the instruction reference in which we use to continue
            //on with vanilla code if our callback doesn't cancel the method.
            //Since we are inserting before the stopDrops = true, we use the
            //first instruction for the setter, which is ldc.i4.1 (which means (bool)true)
            var insContinue = stopDrops.Previous;

            //Inject the callback IL
            processor.InsertBefore(insContinue,
                                                                                            //Create the callback execution
                                   new { OpCodes.Ldarga, Operand = vanilla.Parameters[0] }, //reference to int x
                                   new { OpCodes.Ldarga, Operand = vanilla.Parameters[1] }, //reference to int y
                                   new { OpCodes.Call, callback },                          //OTAPI.Callbacks.Terraria.WordGen.DropMeteor(ref x, ref y)

                                                                                            //If the callback is not canceled, continue on with vanilla code
                                   new { OpCodes.Brtrue_S, insContinue },

                                   //If the callback is canceled, return false
                                   new { OpCodes.Ldc_I4_0 }, //false
                                   new { OpCodes.Ret } //return
                                   );

            /* We now should have code in meteor looking like:
             *      }
             *  }
             *                  if (!WorldGen.DropMeteor(ref i, ref j))
             *                  {
             *                          return false;
             *                  }
             *                  WorldGen.stopDrops = true;
             *                  num = WorldGen.genRand.Next(17, 23);
             */
        }
Ejemplo n.º 11
0
        public override void Run()
        {
            var vanilla  = SourceDefinition.Type("Terraria.Netplay").Method("ServerLoop");
            var callback = this.Method(() => OTAPI.Callbacks.Terraria.Netplay.ServerSocketCreate());

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

            iTcpSocket.OpCode  = OpCodes.Call;                    //Replace newobj to be call as we need to execute out callback instead
            iTcpSocket.Operand = vanilla.Module.Import(callback); //Replace the method reference from the TcpSocket constructor, to our callback
        }
Ejemplo n.º 12
0
        protected virtual void ConvertLine(LuaTextWriter luaWriter, TsvLine line)
        {
            var firstValue = line.Fields.First();

            if (State == null && firstValue.StartsWith("SOURCE"))
            {
                luaWriter.Write("SetSource(");
                SourceDefinition.Parse(line.Fields).Dump(luaWriter);
                luaWriter.Write(")\n");
                return;
            }

            throw new ParseFailedException(firstValue, $"Unknown field {firstValue.Value} seen in state {State}");
        }
Ejemplo n.º 13
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.º 14
0
        public override void Run()
        {
            var netMessage = SourceDefinition.Type <NetMessage>();
            var sendData   = netMessage.Method("SendData");

            // Create new method
            var overloading = new MethodDefinition(sendData.Name, sendData.Attributes, sendData.ReturnType);

            foreach (var p in sendData.Parameters)
            {
                var prm = new ParameterDefinition(p.Name, p.Attributes, p.ParameterType);
                prm.Constant = p.Constant;
                if (prm.ParameterType == SourceDefinition.MainModule.TypeSystem.String)
                {
                    prm.ParameterType = Type <NetworkText>();
                    prm.Constant      = NetworkText.Empty;
                }
                overloading.Parameters.Add(prm);
            }

            // Create method body
            var ilprocessor          = overloading.Body.GetILProcessor();
            ParameterDefinition text = null;

            for (int i = 0; i < overloading.Parameters.Count; i++)
            {
                ilprocessor.Append(Instruction.Create(OpCodes.Ldarg, overloading.Parameters[i]));
                if (overloading.Parameters[i].ParameterType == Type <NetworkText>())
                {
                    text = overloading.Parameters[i];
                    ilprocessor.Append(Instruction.Create(OpCodes.Callvirt, Type <NetworkText>().Method("ToString")));
                }
            }
            ilprocessor.Append(Instruction.Create(OpCodes.Call, sendData));
            ilprocessor.Append(Instruction.Create(OpCodes.Ret));

            foreach (var i in new []
            {
                Instruction.Create(OpCodes.Ldarg, text),
                Instruction.Create(OpCodes.Brtrue_S, overloading.Body.Instructions[0]),
                Instruction.Create(OpCodes.Ldsfld, Type <NetworkText>().Field("Empty")),
                Instruction.Create(OpCodes.Starg, text),
            }.Reverse())
            {
                ilprocessor.InsertBefore(overloading.Body.Instructions[0], i);
            }

            netMessage.Methods.Add(overloading);
        }
Ejemplo n.º 15
0
        public override void Run()
        {
            var vanilla  = SourceDefinition.Type("Terraria.Netplay").Method("OnConnectionAccepted");
            var callback = SourceDefinition.MainModule.Import(
                this.Method(() => OTAPI.Callbacks.Terraria.Netplay.OnConnectionAccepted(null))
                );

            vanilla.Wrap
            (
                beginCallback: callback,
                endCallback: null,
                beginIsCancellable: true,
                noEndHandling: true,
                allowCallbackInstance: false
            );
        }
Ejemplo n.º 16
0
        public override void Run()
        {
            var vanilla = SourceDefinition.Type("Terraria.Projectile").Method("Kill");

            var cbkBegin = this.Method(() => Callbacks.Terraria.Projectile.KillBegin(null));
            var cbkEnd   = this.Method(() => Callbacks.Terraria.Projectile.KillEnd(null));

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

            int    tmp      = 0;
            bool   tmp1     = false;
            string tmp2     = null;
            double tmp3     = 0;
            var    cbkBegin =          //this.SourceDefinition.MainModule.Import(
                              this.Method(() => OTAPI.Callbacks.Terraria.Player.HurtBegin(ref tmp3, null, ref tmp, ref tmp, ref tmp1, ref tmp1, ref tmp2, ref tmp1, ref tmp));

            //);

            vanilla.InjectNonVoidBeginCallback(cbkBegin);
        }
Ejemplo n.º 18
0
        public override void Run()
        {
            var vanilla = SourceDefinition.Type("Terraria.RemoteClient").Method("Reset");

            var cbkBegin = this.Method(() => OTAPI.Callbacks.Terraria.RemoteClient.PreReset(null));
            var cbkEnd   = this.Method(() => OTAPI.Callbacks.Terraria.RemoteClient.PostReset(null));

            vanilla.Wrap
            (
                beginCallback: cbkBegin,
                endCallback: cbkEnd,
                beginIsCancellable: true,
                noEndHandling: false,
                allowCallbackInstance: true
            );
        }
Ejemplo n.º 19
0
        internal static bool TryParseSource(ScriptParser Parser, out SourceDefinition Source)
        {
            Parser.SkipWhiteSpace();

            int        Start = Parser.Position;
            ScriptNode Node  = Parser.ParseNoWhiteSpace();
            ScriptNode Name  = null;
            string     s;

            Parser.SkipWhiteSpace();

            s = Parser.PeekNextToken().ToUpper();
            if (!string.IsNullOrEmpty(s) &&
                IsAlias(s) &&
                s != "INNER" &&
                s != "OUTER" &&
                s != "LEFT" &&
                s != "RIGHT" &&
                s != "FULL" &&
                s != "JOIN" &&
                s != "WHERE" &&
                s != "GROUP" &&
                s != "ORDER" &&
                s != "OFFSET" &&
                s != "ON" &&
                s != "SET" &&
                s != "SELECT" &&
                s != "OBJECT" &&
                s != "OBJECTS")
            {
                if (s == "AS")
                {
                    Parser.NextToken();
                }

                Name = Parser.ParseNoWhiteSpace();
            }
            else if (Node is VariableReference Ref)
            {
                Name = new ConstantElement(new StringValue(Ref.VariableName), Node.Start, Node.Length, Node.Expression);
            }

            Source = new SourceReference(Node, Name, Start, Parser.Position - Start, Parser.Expression);

            return(true);
        }
Ejemplo n.º 20
0
 public async Task Run(SourceDefinition source, CancellationToken token)
 {
     if (source.Source == SourceType.Amazon)
     {
         var amazon = new Amazon(_client, _logger, _runner, source);
         await amazon.Run(token);
     }
     else if (source.Source == SourceType.NewEgg)
     {
         var newEgg = new NewEgg(_client, source);
         await newEgg.Run(token);
     }
     else
     {
         throw new Exception($"Unrecognized source type {source.Source}");
     }
 }
Ejemplo n.º 21
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.º 22
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
            );
        }
Ejemplo n.º 23
0
        public override void Run()
        {
            var vanilla      = SourceDefinition.Type("Terraria.NPC").Method("Transform");
            int tmp          = 0;
            var preCallback  = vanilla.Module.Import(this.Method(() => OTAPI.Callbacks.Terraria.Npc.PreTransform(null, ref tmp)));
            var postCallback = vanilla.Module.Import(this.Method(() => OTAPI.Callbacks.Terraria.Npc.PostTransform(null)));

            //We could wrap this method, but this hooks is to inform when an npc transforms, not
            //an occurrence of the call.
            //Anyway, this instance we need to insert before the netMode == 2 check.

            //Get the IL processor instance so we can modify IL
            var processor = vanilla.Body.GetILProcessor();

            //Pre callback section
            {
                var first = vanilla.Body.Instructions.First();
                processor.InsertBefore(first,
                                       new { OpCodes.Ldarg_0 },
                                       new { OpCodes.Ldarga, Operand = vanilla.Parameters.Single() },
                                       new { OpCodes.Call, Operand = preCallback },
                                       new { OpCodes.Brtrue_S, Operand = first },
                                       new { OpCodes.Ret }
                                       );
            }

            //Post callback section
            {
                var insertionPoint = vanilla.Body.Instructions.Single(x => x.OpCode == OpCodes.Ldsfld &&
                                                                      x.Operand is FieldReference &&
                                                                      (x.Operand as FieldReference).Name == "netMode" &&
                                                                      x.Next.OpCode == OpCodes.Ldc_I4_2
                                                                      );

                //Insert our callback before the if block, ensuring we consider that the if block may be referenced elsewhere
                Instruction ourEntry;
                processor.InsertBefore(insertionPoint, ourEntry = processor.Create(OpCodes.Ldarg_0));                 //Add the current instance (this in C#) to the callback
                processor.InsertBefore(insertionPoint, processor.Create(OpCodes.Call, postCallback));

                //Replace transfers
                insertionPoint.ReplaceTransfer(ourEntry, vanilla);
            }
        }
        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.º 25
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.º 26
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.º 27
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.º 28
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.º 29
0
        public override void Run()
        {
            //Get the vanilla method reference
            var vanilla = SourceDefinition.Type("Terraria.WorldGen").Method("hardUpdateWorld");

            //Get the OTAPI callback method reference
            //int tmp = 0;
            var callback = this.SourceDefinition.MainModule.Import(
                this.Method(() => OTAPI.Callbacks.Terraria.WorldGen.HardmodeTilePlace(0, 0, 0, false, false, 0, 0))
                );

            /* In this particular hardmode tile mod we replace all WorldGen.PlaceTile
             * calls to a custom callback version, then replace the Pop instruction
             * with cancelable IL.
             */

            var targets = vanilla.Body.Instructions.Where(instruction =>
                                                          instruction.OpCode == OpCodes.Call &&
                                                          (instruction.Operand as MethodReference).Name == "PlaceTile"

                                                          && instruction.Next.OpCode == OpCodes.Pop
                                                          ).ToArray();

            var processor = vanilla.Body.GetILProcessor();

            foreach (var replacementPoint in targets)            //.Take(1))
            {
                replacementPoint.Operand = callback;


                var insContinue = replacementPoint.Next.Next.Next(i =>
                                                                  i.OpCode == OpCodes.Call &&
                                                                  (i.Operand as MethodReference).Name == "SendTileSquare"
                                                                  ).Next;

                replacementPoint.Next.OpCode  = OpCodes.Brtrue_S;
                replacementPoint.Next.Operand = insContinue;

                processor.InsertAfter(replacementPoint.Next, processor.Create(OpCodes.Ret));
            }
        }
Ejemplo n.º 30
0
        public override void Run()
        {
            var vanilla = SourceDefinition.Type("Terraria.Item").Methods.Single(
                x => x.Name == "SetDefaults" &&
                x.Parameters.First().ParameterType == this.SourceDefinition.MainModule.TypeSystem.Int32 &&
                x.Parameters.Skip(1).First().ParameterType == this.SourceDefinition.MainModule.TypeSystem.Boolean
                );


            var cbkBegin = this.ModificationDefinition.Type("OTAPI.Callbacks.Terraria.Item").Method("SetDefaultsByIdBegin", parameters: vanilla.Parameters);
            var cbkEnd   = this.ModificationDefinition.Type("OTAPI.Callbacks.Terraria.Item").Method("SetDefaultsByIdEnd", parameters: vanilla.Parameters);

            vanilla.Wrap
            (
                beginCallback: cbkBegin,
                endCallback: cbkEnd,
                beginIsCancellable: true,
                noEndHandling: false,
                allowCallbackInstance: true
            );
        }
 /// <summary>
 /// The add expression to collection.
 /// </summary>
 /// <param name="source">
 /// The source.
 /// </param>
 /// <param name="hookType">
 /// The hook type.
 /// </param>
 /// <param name="description">
 /// The description.
 /// </param>
 /// <param name="processDescription">
 /// The process description.
 /// </param>
 /// <param name="expression">
 /// The expression.
 /// </param>
 /// <param name="sysid">
 /// The sysid.
 /// </param>
 private void AddExpressionToCollection(
     SourceDefinition source,
     SourceDefinition hookType,
     string description,
     DefinitionDescription processDescription,
     string expression,
     string sysid = "")
 {
     JobManager.RunInDispatcherThread(
         DebugWindowManager.DebugConsoleWindow.Dispatcher,
         DispatcherPriority.Normal,
         delegate
             {
                 try
                 {
                     switch (source)
                     {
                         case SourceDefinition.Field:
                             this.AddItemToCollection(
                                 processDescription.DictionaryExpressions,
                                 new SBExpression(processDescription.FileName, expression, hookType, sysid)
                                     {
                                         Description =
                                             description
                                     });
                             break;
                         case SourceDefinition.Screen:
                             /*
                             if (hookType == SourceDefinition.Process)
                             {
                                 //AddItemToCollection(processDescription.ProcessCollection, );
                                 this.AddProcessToCollection(
                                     description,
                                     processDescription,
                                     new SBExpression(processDescription.FileName, expression, hookType, sysid, expression)
                                         {
                                             Description
                                                 =
                                                 description
                                         });
                             }
                             else
                             {
     */
                             this.AddItemToCollection(
                                 processDescription.ScreenExpressions,
                                 new SBExpression(processDescription.FileName, expression, hookType, sysid)
                                     {
                                         Description =
                                             description
                                     });
                             /*
                             }
     */
                             break;
                         case SourceDefinition.Menu:
                             this.AddProcessToCollection(
                                 description,
                                 processDescription,
                                 new SBExpression(processDescription.FileName, expression, hookType, sysid, expression)
                                     {
                                         Description
                                             =
                                             description
                                     });
                             break;
                         case SourceDefinition.Paragraph:
                             this.AddItemToCollection(
                                 processDescription.Expressions,
                                 new SBExpression(processDescription.FileName, expression, hookType, sysid)
                                     {
                                         Description =
                                             description
                                     });
                             break;
                         case SourceDefinition.Unknown:
                             this.AddItemToCollection(
                                 processDescription.Expressions,
                                 new SBExpression(processDescription.FileName, expression, hookType, sysid)
                                     {
                                         Description =
                                             description
                                     });
                             break;
                     }
                 }
                 catch (Exception exception)
                 {
                     CustomLogger.LogException(exception, "Problem adding expression to the collection.");
                 }
             });
 }
        /// <summary>
        /// Loads the definition from expression.
        /// </summary>
        /// <param name="source">
        /// Where the expression is being called from.
        /// </param>
        /// <param name="hookType">
        /// If this is a process hook point or expression hook point.
        /// </param>
        /// <param name="expression">
        /// The original expression that the definition name was derrived from.
        /// </param>
        /// <param name="parent">
        /// Parent <see cref="DefinitionDescription"/>, if this is null then it will be the root of the tree.
        /// </param>
        /// <param name="hookPoint">
        /// The name of the definition slot where the definition was found.
        /// </param>
        /// <param name="sysid">
        /// The system id to use otherwise the current system id will be used.
        /// </param>
        internal void LoadProcessFromExpression(
            SourceDefinition source,
            SourceDefinition hookType,
            string expression,
            DefinitionDescription parent = null,
            string hookPoint = "",
            string sysid = "")
        {
            if (string.IsNullOrEmpty(expression))
            {
                // there is no expression so no need to try load it.
                return;
            }

            if (expression.StartsWith("P.CALL.PROCESS"))
            {
                // this is specific to American Auto Shield. The have a process used to call other processes so we can just remove it.
                expression = expression.Substring(15);
            }

            // Check to see if it is a constant, if so just add it to the collection.
            if (SBExpression.IsConstantValueExpression(expression))
            {
                this.AddExpressionToCollection(source, hookType, hookPoint, parent, expression);
                return;
            }

            var colonPos = expression.IndexOf(":", StringComparison.Ordinal);
            if (colonPos != 1)
            {
                // SB expression that have an identified, i.e. B: D: all have a single character then a ':'
                colonPos = 0;
            }

            // a field definition has no process hooks they are all expressions, etc. int help.
            if (source != SourceDefinition.Paragraph
                && (colonPos > 0 || source == SourceDefinition.Field || source == SourceDefinition.Expression))
            {
                this.AddExpressionToCollection(source, hookType, hookPoint, parent, expression);
                return;
            }

            string callType;
            var pName = GetProcessName(expression, out callType);
            if (!string.IsNullOrEmpty(pName))
            {
                switch (callType)
                {
                    case "C":
                        this.LoadProcess(pName, source, hookType, parent, expression, hookPoint, sysid);
                        break;
                    case "B":
                        this.LoadBasicProgramFromExpression(pName, parent, hookPoint);
                        break;
                    case "M":
                        break;
                    case "D":
                        this.AddExpressionToCollection(source, hookType, hookPoint, parent, expression);
                        break;
                    case "V":
                        this.AddExpressionToCollection(source, hookType, hookPoint, parent, expression);
                        break;
                    default:
                        this.LoadProcess(pName, source, hookType, parent, expression, hookPoint, sysid);
                        break;
                }
            }
        }
        /// <summary>
        /// Loads the definition from xxPROCESS.
        /// </summary>
        /// <param name="pName">
        /// Name of the definition.
        /// </param>
        /// <param name="slotType"></param>
        /// <param name="parent">
        /// Parent <see cref="DefinitionDescription"/>, if this is null then it will be the root of the tree.
        /// </param>
        /// <param name="expression">
        /// The original expression that the definition name was derrived from.
        /// </param>
        /// <param name="hookPoint">
        /// The name of the definition slot where the definition was found.
        /// </param>
        /// <param name="sysid">
        /// The system id to use otherwise the current system id will be used.
        /// </param>
        /// <param name="source"></param>
        internal void LoadProcess(
            string pName,
            SourceDefinition source,
            SourceDefinition slotType,
            DefinitionDescription parent = null,
            string expression = "",
            string hookPoint = "",
            string sysid = "")
        {
            if (SBExpression.IsStandardSBExpression(expression))
            {
                // standard SB expression elements and therefore no need to try read the process, just add the element
                this.AddExpressionToCollection(parent, hookPoint, expression);
                return;
            }

            if (string.IsNullOrEmpty(expression))
            {
                expression = pName;
            }

            JobManager.RunInUIThread(
                DispatcherPriority.Input,
                delegate
                    {
                        var processFile = sysid;
                        if (string.IsNullOrEmpty(processFile))
                        {
                            processFile = SBPlusClient.Current.SystemId;
                        }

                        // read definition record from current xxProcess
                        processFile += "PROCESS";
                        // check if I already have the definition in the collection
                        lock (this.processCollection)
                        {
                            if (this.processCollection.ContainsKey(processFile, pName))
                            {
                                this.SetIsLoading(1);
                                this.AddProcessToCollection(pName, parent, this.processCollection[pName]);
                                this.SetIsLoading(-1);
                                return;
                            }
                        }

                        this.SetIsLoading(1);
                        SBFile.Read(
                            processFile,
                            pName,
                            this.ReadProcessCompleted,
                            new ProcessLoadState { HookPoint = hookPoint, ParentDefinitionDescription = parent, Expression = expression, Source = source, SlotType = slotType, SysId = sysid });
                    });
        }
        /// <summary>
        /// The add process to collection.
        /// </summary>
        /// <param name="description">
        /// The description.
        /// </param>
        /// <param name="parentDefinitionDescription">
        /// The parent definition description.
        /// </param>
        /// <param name="processDescription">
        /// The process description.
        /// </param>
        /// <param name="source">Where is the process being called from.</param>
        private void AddProcessToCollection(
            string description,
            DefinitionDescription parentDefinitionDescription,
            DefinitionDescription processDescription,
            SourceDefinition source = SourceDefinition.Unknown)
        {
            JobManager.RunInDispatcherThread(
                DebugWindowManager.DebugConsoleWindow.Dispatcher,
                DispatcherPriority.Normal,
                delegate
                    {
                        if (parentDefinitionDescription == null)
                        {
                            this.Definition = processDescription;
                            this.ResetAnalysis();
                            this.ProcessStack.Push(this.Definition);
                        }
                        else
                        {
                            switch (source)
                            {
                                case SourceDefinition.Screen:
                                    if (processDescription is SBExpression)
                                    {
                                        this.AddItemToCollection(parentDefinitionDescription.ScreenExpressions, processDescription as SBExpression);
                                    }
                                    else
                                    {
                                        this.AddItemToCollection(
                                            parentDefinitionDescription.ProcessCollection,
                                            new ProcessCall { Description = description, ProcessDescription = processDescription });
                                    }
                                    break;
                                case SourceDefinition.Button:
                                    //this.AddItemToCollection(description, processDescription, parentDefinitionDescription.ProcessCollection);
                                    this.AddItemToCollection(
                                        parentDefinitionDescription.ProcessCollection,
                                        new ProcessCall { Description = description, ProcessDescription = processDescription });

                                    break;
                                default:
                                    this.AddItemToCollection(
                                        parentDefinitionDescription.ProcessCollection,
                                        new ProcessCall { Description = description, ProcessDescription = processDescription });
                                    break;
                            }
                        }
                    });
        }
 public ButtonDefinitionDescription(string fileName, string name, SourceDefinition hookType, string expression)
     : base(fileName, name, hookType, expression)
 {
 }
Ejemplo n.º 36
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SBExpression"/> class.
 /// </summary>
 /// <param name="fileName">
 /// The file name.
 /// </param>
 /// <param name="expression">
 /// The expression.
 /// </param>
 /// <param name="hookType">
 /// The hook type.
 /// </param>
 /// <param name="sysid">
 /// The sysid.
 /// </param>
 public SBExpression(string fileName, string expression, SourceDefinition hookType, string sysid)
     : this(fileName, expression, hookType, sysid, string.Empty)
 {
 }
Ejemplo n.º 37
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SBExpression"/> class.
 /// </summary>
 /// <param name="fileName">
 /// The file name.
 /// </param>
 /// <param name="expression">
 /// The expression.
 /// </param>
 /// <param name="hookType">
 /// The hook type.
 /// </param>
 /// <param name="sysid">
 /// The sysid.
 /// </param>
 /// <param name="name">
 /// The name.
 /// </param>
 public SBExpression(string fileName, string expression, SourceDefinition hookType, string sysid, string name)
     : base(fileName, name, hookType, expression)
 {
     this.SystemId = sysid;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="SelectionProcessDescription"/> class.
 /// </summary>
 /// <param name="fileName">
 /// The file name.
 /// </param>
 /// <param name="name">
 /// The name.
 /// </param>
 /// <param name="definition">
 /// The definition.
 /// </param>
 public SelectionProcessDescription(string fileName, string name, SourceDefinition hookType, string sysId, SBString definition)
     : base(fileName, name, hookType, sysId)
 {
     this.Name = name;
 }