示例#1
0
        /// <summary>
        /// Creates a blank texture you can use. Libvaxy will automatically dispose this texture on unload.
        /// </summary>
        /// <param name="width">The width of the texture.</param>
        /// <param name="height">The height of the texture.</param>
        /// <returns>The newly created texture.</returns>
        public static Texture2D CreateTexture(int width, int height)
        {
            Texture2D texture = new Texture2D(Main.graphics.GraphicsDevice, width, height);

            LibvaxyMod.DisposeOnUnload(texture);
            return(texture);
        }
示例#2
0
        internal static void ApplyFieldSets()
        {
            foreach (MethodInfo method in Reflection.GetMethodsWithAttribute <FieldSetAttribute>())
            {
                if (method.ReturnType != typeof(void))
                {
                    throw new LibvaxyException($"The FieldSet method '{method.FullMemberName()}' must have a return type of void");
                }

                if (method.GetCustomAttribute <ExtensionAttribute>() == null)
                {
                    throw new LibvaxyException($"The FieldSet method '{method.FullMemberName()} must be an extension method targetting the type with the specified field");
                }

                ParameterInfo[] parameters = method.GetParameters();

                if (parameters.Length != 2)
                {
                    throw new LibvaxyException($"The FieldSet method '{method.FullMemberName()}' must have a second parameter whose type matches the specified field's type");
                }

                Type targetType             = parameters[0].ParameterType;
                FieldSetAttribute attribute = method.GetCustomAttribute <FieldSetAttribute>();

                if (!Reflection.HasField(targetType, attribute.fieldName))
                {
                    throw new LibvaxyException($"The FieldSet method '{method.FullMemberName()}' targets field '{attribute.fieldName}' which does not exist in type '{targetType.FullName}'");
                }

                FieldInfo     targetFieldInfo = Reflection.GetFieldInfo(targetType, attribute.fieldName);
                ParameterInfo valueParameter  = parameters[1];

                if (valueParameter.ParameterType != targetFieldInfo.FieldType)
                {
                    throw new LibvaxyException($"The setter parameter '{valueParameter.Name}' in the FieldSet method '{method.FullMemberName()}' does not have a type matching the target field '{attribute.fieldName}'");
                }

                ILHook hook = new ILHook(method, il =>
                {
                    il.Body.Instructions.Clear();
                    ILCursor cursor = new ILCursor(il);

                    cursor.Emit(OpCodes.Ldarg_1);

                    if (targetFieldInfo.IsStatic)
                    {
                        cursor.Emit(OpCodes.Stsfld, targetFieldInfo);
                    }
                    else
                    {
                        cursor.Emit(OpCodes.Ldarg_0);
                        cursor.Emit(OpCodes.Stfld, targetFieldInfo);
                    }

                    cursor.Emit(OpCodes.Ret);
                });

                LibvaxyMod.DisposeOnUnload(hook);
            }
        }
示例#3
0
        /// <summary>
        /// Clones a certain rectangle within a texture and returns a new Texture2D object for it. Libvaxy will automatically dispose the cloned texture on unload.
        /// </summary>
        /// <param name="rect">The rectangle within the texture to clone.</param>
        /// <returns>The cloned texture rectangle.</returns>
        public static Texture2D CloneRectangle(this Texture2D texture, Rectangle rect)
        {
            Texture2D newTexture = new Texture2D(Main.instance.GraphicsDevice, rect.Width, rect.Height);

            Color[] colors = texture.GetColorsRect(rect);
            newTexture.SetData(colors);
            LibvaxyMod.DisposeOnUnload(newTexture);
            return(newTexture);
        }
示例#4
0
        /// <summary>
        /// Clones a certain texture and returns a new Texture2D object for it. Libvaxy will automatically dispose the cloned texture on unload.
        /// </summary>
        /// <returns>The cloned texture.</returns>
        public static Texture2D Clone(this Texture2D texture)
        {
            Color[]   colors     = texture.GetColors();
            Texture2D newTexture = new Texture2D(Main.instance.GraphicsDevice, texture.Width, texture.Height);

            newTexture.SetData(colors);
            LibvaxyMod.DisposeOnUnload(newTexture);
            return(newTexture);
        }
示例#5
0
        public override bool PreDraw(SpriteBatch spriteBatch, Color lightColor)
        {
            int tileType = (int)projectile.ai[0];

            if (!LibvaxyMod.FallingTileTextures.ContainsKey(tileType))
            {
                LibvaxyMod.FallingTileTextures[tileType] = LibvaxyMod.CreateFallingTileTexture(tileType);
            }

            spriteBatch.Draw(LibvaxyMod.FallingTileTextures[tileType], projectile.position - Main.screenPosition, null, lightColor, projectile.rotation, new Vector2(projectile.width / 2, projectile.height / 2), 1f, SpriteEffects.None, 0f);
            return(false);
        }
示例#6
0
        internal static void ApplyFieldGets()
        {
            foreach (MethodInfo method in Reflection.GetMethodsWithAttribute <FieldGetAttribute>())
            {
                if (method.ReturnType == typeof(void))
                {
                    throw new LibvaxyException($"The FieldGet method '{method.FullMemberName()}' cannot have a return type of void");
                }

                if (method.GetCustomAttribute <ExtensionAttribute>() == null)
                {
                    throw new LibvaxyException($"The FieldGet method '{method.FullMemberName()} must be an extension method targetting the type with the specified field");
                }

                Type targetType             = method.GetParameters()[0].ParameterType;
                FieldGetAttribute attribute = method.GetCustomAttribute <FieldGetAttribute>();

                if (!Reflection.HasField(targetType, attribute.fieldName))
                {
                    throw new LibvaxyException($"The FieldGet method '{method.FullMemberName()}' targets field '{attribute.fieldName}' which does not exist in type '{targetType.FullName}'");
                }

                ILHook hook = new ILHook(method, il =>
                {
                    il.Body.Instructions.Clear();
                    ILCursor cursor = new ILCursor(il);

                    FieldInfo targetFieldInfo = Reflection.GetFieldInfo(targetType, attribute.fieldName);

                    if (targetFieldInfo.IsStatic)
                    {
                        cursor.Emit(OpCodes.Ldsfld, targetFieldInfo);
                    }
                    else
                    {
                        cursor.Emit(OpCodes.Ldarg_0);
                        cursor.Emit(OpCodes.Ldfld, targetFieldInfo);
                    }

                    cursor.Emit(OpCodes.Ret);
                });

                LibvaxyMod.DisposeOnUnload(hook);
            }
        }
示例#7
0
        // TODO: Make it possible to call original method easily + pass in an instance of the caller
        internal static void ApplyDetours()
        {
            MonoModHooks.RequestNativeAccess();

            foreach (MethodInfo method in Reflection.GetMethodsWithAttribute <DetourAttribute>())
            {
                DetourAttribute attribute = method.GetCustomAttribute <DetourAttribute>();
                string          modName   = attribute.typeName.Split('.')[0];

                if (!LibvaxyMod.ModAssemblies.ContainsKey(modName))
                {
                    LibvaxyMod.Logger.Warn("Attempted to detour an unknown / unloaded mod, ignoring and moving on...");
                    continue;
                }

                Type targetMethodType = LibvaxyMod.ModAssemblies[modName].GetType(attribute.typeName);

                if (targetMethodType == null)
                {
                    throw new LibvaxyException("Could not find the target type to perform detour");
                }

                MethodInfo targetMethod = Reflection.GetMethodInfo(targetMethodType, attribute.methodName, attribute.parameterTypes ?? new Type[0]);

                // TODO: move these checks elsewhere as a utility
                if (targetMethod == null)
                {
                    throw new LibvaxyException("Could not find the target method to perform detour");
                }

                if (!Reflection.GetParameterTypes(method).SequenceEqual(Reflection.GetParameterTypes(targetMethod)))
                {
                    throw new LibvaxyException("The target method and detour method do not have matching parameter types");
                }

                if (method.ReturnType != targetMethod.ReturnType)
                {
                    throw new LibvaxyException("The target method and detour method do not have matching return types");
                }

                LibvaxyMod.DisposeOnUnload(new Detour(targetMethod, method));
                LibvaxyMod.Logger.Info($"Registered detour from {targetMethod.FullMemberName()}\nTo: {method.FullMemberName()}");
            }
        }
示例#8
0
        internal static void ApplyMethodInvokers()
        {
            foreach (MethodInfo method in Reflection.GetMethodsWithAttribute <MethodInvokerAttribute>())
            {
                if (method.GetCustomAttribute <ExtensionAttribute>() == null)
                {
                    throw new LibvaxyException($"The MethodInvoker method '{method.FullMemberName()}' must be an extension method targetting the type with the specified target method");
                }

                MethodInvokerAttribute attribute = method.GetCustomAttribute <MethodInvokerAttribute>();
                Type targetType = method.GetParameters()[0].ParameterType;

                if (!Reflection.HasMethod(targetType, attribute.methodName))
                {
                    throw new LibvaxyException($"The MethodInvoker method '{method.FullMemberName()}' targets method '{attribute.methodName}' which does not exist in type '{targetType.FullName}'");
                }

                MethodInfo targetMethodInfo = Reflection.GetMethodInfo(targetType, attribute.methodName, Reflection.GetParameterTypes(method).Skip(1).ToArray());

                if (method.ReturnType != targetMethodInfo.ReturnType && targetMethodInfo.ReturnType.IsSubclassOf(method.ReturnType))
                {
                    throw new LibvaxyException($"The MethodInvoker method '{method.FullMemberName()}' does not have a return type that matches or is a parent of the return type of the targetted method '{attribute.methodName}'");
                }

                Type[] targetMethodParameterTypes = Reflection.GetParameterTypes(targetMethodInfo);
                int    parameterCount             = targetMethodParameterTypes.Length;

                if (!Reflection.GetParameterTypes(method).Skip(1).SequenceEqual(targetMethodParameterTypes))
                {
                    throw new LibvaxyException($"The MethodInvoker method '{method.FullMemberName()}' does not have parameter types that match the targetted method '{attribute.methodName}'");
                }

                ILHook hook = new ILHook(method, il =>
                {
                    il.Body.Instructions.Clear();
                    ILCursor cursor = new ILCursor(il);

                    if (!targetMethodInfo.IsStatic)
                    {
                        cursor.Emit(OpCodes.Ldarg_0);
                    }

                    for (int i = 1; i <= parameterCount; i++)
                    {
                        switch (i)
                        {
                        case 1:
                            cursor.Emit(OpCodes.Ldarg_1);
                            break;

                        case 2:
                            cursor.Emit(OpCodes.Ldarg_2);
                            break;

                        case 3:
                            cursor.Emit(OpCodes.Ldarg_3);
                            break;

                        default:
                            cursor.Emit(OpCodes.Ldarg_S, (byte)i);
                            break;
                        }
                    }

                    cursor.Emit(OpCodes.Call, targetMethodInfo);
                    cursor.Emit(OpCodes.Ret);
                });

                LibvaxyMod.DisposeOnUnload(hook);
            }
        }