Exemplo n.º 1
0
        /// <summary>
        /// Removes an element from the music stack. If this was the top element, this will trigger a transition to the next element.
        /// </summary>
        public void RemoveFromMusicStack(PrioritySortingKey key)
        {
            Asserts.AssertTrue(musicStack.ContainsKey(key), "This key is not in the music stack!");
            var  keyMusic           = musicStack[key];
            bool wasPlayingKeyMusic = keyMusic == currentMusic;

            musicStack.Remove(key);
            if (wasPlayingKeyMusic)
            {
                TransitionToMusic(keyMusic, currentMusic, keyMusic.GetReleaseControlTransition());
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Adds an elment to the music stack. If this becomes the top element, it will transition to these music settings.
        /// </summary>
        public PrioritySortingKey AddToMusicStack(IMusicStackElement addedMusic)
        {
            var prevMusic = currentMusic;

            var newKey = new PrioritySortingKey((int)addedMusic.GetPriority());

            musicStack.Add(newKey, addedMusic);

            if (currentMusic != prevMusic)
            {
                Asserts.AssertTrue(addedMusic == currentMusic, "Somehow we added to the music stack and yet a different music rose to the top?");
                TransitionToMusic(prevMusic, currentMusic, currentMusic.GetTakeControlTransition());
            }
            return(newKey);
        }
Exemplo n.º 3
0
        private FieldReference FixFieldReference(FieldReference yourFieldRef)
        {
            if (yourFieldRef == null)
            {
                Log_called_to_fix_null("field");
                return(null);
            }
            Log_fixing_reference("field", yourFieldRef);
            Asserts.AssertTrue(yourFieldRef.DeclaringType != null);

            var yourFieldDef = yourFieldRef.Resolve();

            if (yourFieldDef.IsDisablePatching())
            {
                Log_trying_to_fix_disabled_reference("field", yourFieldRef);
            }
            var targetType         = FixTypeReference(yourFieldRef.DeclaringType);
            var targetBaseFieldDef = yourFieldRef;

            if (yourFieldDef.Module.Assembly.IsPatchingAssembly())
            {
                //additional checking
                var targetFieldDef = targetType.Resolve().GetField(yourFieldDef.Name);
                if (targetFieldDef == null)
                {
                    throw Errors.Could_not_resolve_reference("field", yourFieldRef);
                }
                targetBaseFieldDef = targetFieldDef;
            }
            else
            {
                //we assume that types that aren't in a patching assembly will never reference types in a patching assembly
                targetBaseFieldDef = yourFieldRef;
            }
            var newMethodRef = targetBaseFieldDef.MakeReference();

            newMethodRef.DeclaringType = targetType;
            newMethodRef.FieldType     = FixTypeReference(newMethodRef.FieldType);
            var targetFieldRef = TargetAssembly.MainModule.Import(newMethodRef);

            Log_fixed_reference("field", yourFieldRef, targetFieldRef);
            targetFieldRef.Module.Assembly.AssertEqual(TargetAssembly);

            return(targetFieldRef);
        }
Exemplo n.º 4
0
        /// <summary>
        ///     Fixes the method reference.
        /// </summary>
        /// <param name="yourMethodRef">The method reference.</param>
        /// <param name="isFixTypeCalling">This parameter is sort of a hack that lets FixType call FixMethod to fix MVars, without infinite recursion. If set to false, it avoids fixing some types.</param>
        /// <returns></returns>
        /// <exception cref="Exception">Method isn't part of a patching type in this assembly...</exception>
        private MethodReference FixMethodReference(MethodReference yourMethodRef, bool isFixTypeCalling = true)
        {
            //Fixes reference like YourAssembly::PatchingClass::Method to TargetAssembly::PatchedClass::Method
            if (yourMethodRef == null)
            {
                Log_called_to_fix_null("method");
                return(null);
            }
            Log_fixing_reference("method", yourMethodRef);
            Asserts.AssertTrue(yourMethodRef.DeclaringType != null);
            var yourMethodDef = yourMethodRef.Resolve();

            if (yourMethodDef.IsDisablePatching())
            {
                Log_trying_to_fix_disabled_reference("method", yourMethodDef);
            }

            /*
             * In comparison to types, method references to methods are pretty simple. There are only two kinds:
             * 1. A regular method reference
             * 2. A reference to an instantiated generic method, e.g. Create<int>
             *
             * 3. As a special case, any method reference (assume non-generic) that has a generic DeclaringType.
             */
            int             hadGenericParams = yourMethodRef.GenericParameters.Count;
            MethodReference targetMethodRef;
            var             memberAlias = yourMethodDef.GetCustomAttribute <MemberAliasAttribute>();

            if (yourMethodRef.IsGenericInstance)
            {
                var yourGeneric             = (GenericInstanceMethod)yourMethodRef;
                var targetBaseMethod        = FixMethodReference(yourGeneric.ElementMethod);
                var targetGenericInstMethod = new GenericInstanceMethod(targetBaseMethod);

                foreach (var arg in yourGeneric.GenericArguments)
                {
                    var targetGenericArg = FixTypeReference(arg);
                    targetGenericInstMethod.GenericArguments.Add(targetGenericArg);
                }
                targetMethodRef = targetGenericInstMethod;
            }
            else
            {
                TypeReference typeToFix = yourMethodRef.DeclaringType;
                if (memberAlias != null && memberAlias.AliasedMemberDeclaringType != null)
                {
                    typeToFix = (TypeReference)memberAlias.AliasedMemberDeclaringType;
                }
                var targetType          = FixTypeReference(typeToFix);
                var targetBaseMethodDef = yourMethodRef;
                if (yourMethodDef.Module.Assembly.IsPatchingAssembly())
                {
                    //additional checking
                    var methodName      = memberAlias == null || memberAlias.AliasedMemberName == null ? yourMethodRef.Name : memberAlias.AliasedMemberName;
                    var targetMethodDef =
                        targetType.Resolve().GetMethods(methodName, yourMethodRef.Parameters.Select(x => x.ParameterType)).SingleOrDefault
                            ();
                    var debugOverloads =
                        targetType.Resolve().Methods.Where(x => x.Name == yourMethodRef.Name).ToArray();
                    if (targetMethodDef == null)
                    {
                        throw Errors.Could_not_resolve_reference("method", yourMethodRef);
                    }
                    targetBaseMethodDef = targetMethodDef;
                }
                else
                {
                    targetBaseMethodDef = yourMethodRef;
                }
                var newMethodRef = targetBaseMethodDef.MakeReference();
                newMethodRef.DeclaringType = targetType;
                targetMethodRef            = newMethodRef;
            }

            if (isFixTypeCalling)
            {
                targetMethodRef = ManualImportMethod(targetMethodRef);
            }
            targetMethodRef = TargetAssembly.MainModule.Import(targetMethodRef);             //for good measure...
            targetMethodRef.Module.Assembly.AssertEqual(TargetAssembly);
            Log_fixed_reference("method", yourMethodRef, targetMethodRef);
            return(targetMethodRef);
        }
Exemplo n.º 5
0
        /// <summary>
        ///     Fixes the method reference.
        /// </summary>
        /// <param name="yourMethodRef">The method reference.</param>
        /// <param name="isntFixTypeCall">This parameter is sort of a hack that lets FixType call FixMethod to fix MVars, without infinite recursion. If set to false, it avoids fixing some types.</param>
        /// <returns></returns>
        /// <exception cref="Exception">Method isn't part of a patching type in this assembly...</exception>
        private MethodReference FixMethodReference(MethodReference yourMethodRef, bool isntFixTypeCall = true)
        {
            //Fixes reference like YourAssembly::PatchingClass::Method to TargetAssembly::PatchedClass::Method
            if (yourMethodRef == null)
            {
                Log_called_to_fix_null("method");
                return(null);
            }
            Log_fixing_reference("method", yourMethodRef);
            Asserts.AssertTrue(yourMethodRef.DeclaringType != null);
            var yourMethodDef = yourMethodRef.Resolve();

            if (yourMethodDef.IsDisablePatching())
            {
                Log_trying_to_fix_disabled_reference("method", yourMethodDef);
            }

            /*
             * In comparison to types, method references to methods are pretty simple. There are only two kinds:
             * 1. A regular method reference
             * 2. A reference to an instantiated generic method, e.g. Create<int>
             *
             * 3. As a special case, any method reference (assume non-generic) that has a generic DeclaringType.
             */
            MethodReference targetMethodRef;

            if (yourMethodRef.IsGenericInstance)
            {
                var yourGeneric             = (GenericInstanceMethod)yourMethodRef;
                var targetBaseMethod        = FixMethodReference(yourGeneric.ElementMethod);
                var targetGenericInstMethod = new GenericInstanceMethod(targetBaseMethod);

                foreach (var arg in yourGeneric.GenericArguments)
                {
                    var targetGenericArg = FixTypeReference(arg);
                    targetGenericInstMethod.GenericArguments.Add(targetGenericArg);
                }
                targetMethodRef = targetGenericInstMethod;
            }
            else
            {
                TypeReference typeToFix   = yourMethodRef.DeclaringType;
                var           action      = CurrentMemberCache.Methods.TryGet(yourMethodDef);
                var           memberAlias = action?.ActionAttribute as MemberAliasAttribute;
                if (memberAlias?.AliasedMemberDeclaringType != null)
                {
                    typeToFix = (TypeReference)memberAlias.AliasedMemberDeclaringType;
                }
                var targetType          = FixTypeReference(typeToFix);
                var targetBaseMethodDef = yourMethodRef;
                if (yourMethodDef.Module.Assembly.IsPatchingAssembly())
                {
                    var targetMethodDef = action?.TargetMember;
                    if (targetMethodDef == null)
                    {
                        throw Errors.Could_not_resolve_reference("method", yourMethodRef);
                    }
                    targetBaseMethodDef = targetMethodDef;
                }
                else
                {
                    targetBaseMethodDef = yourMethodRef;
                }
                var newMethodRef = targetBaseMethodDef.CloneReference();
                newMethodRef.DeclaringType = targetType;
                targetMethodRef            = newMethodRef;
                if (isntFixTypeCall)
                {
                    targetMethodRef = ManualImportMethod(targetMethodRef);
                }
            }

            targetMethodRef.Module.Assembly.AssertEqual(TargetAssembly);
            Log_fixed_reference("method", yourMethodRef, targetMethodRef);
            return(targetMethodRef);
        }