Пример #1
0
        /// <summary>
        /// Gets all the mods and patches them.
        /// </summary>
        private void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            _errorLevel = ErrorLevel.NoError;

            //Gets the list of mods
            ItemCollection modCollection = null;
            string         lolLocation   = null;

            //Get the data from the UI thread
            Dispatcher.Invoke(DispatcherPriority.Input, new ThreadStart(() =>
            {
                modCollection = ModsListBox.Items;
                lolLocation   = LocationTextbox.Text;
            }));

            SetStatusLabelAsync("Gathering mods...");

            //Gets the list of mods that have been checked.
            List <LessMod> modsToPatch = new List <LessMod>();

            foreach (var x in modCollection)
            {
                CheckBox box          = (CheckBox)x;
                bool     isBoxChecked = false;
                Dispatcher.Invoke(DispatcherPriority.Input, new ThreadStart(() =>
                {
                    isBoxChecked = box.IsChecked ?? false;
                }));

                if (isBoxChecked)
                {
                    modsToPatch.Add(_lessMods[box]);
                }
            }

            //Create a new dictionary to hold the SWF definitions in. This stops opening and closing the same SWF file if it's going to be modified more than once.
            Dictionary <string, SwfFile> swfs = new Dictionary <string, SwfFile>();

            //Start the stopwatch to see how long it took to patch (aiming for ~5 sec or less on test machine)
            timer = Stopwatch.StartNew();

            //Go through each modification
            foreach (var lessMod in modsToPatch)
            {
                SetStatusLabelAsync("Patching mod: " + lessMod.Name);

                //Go through each patch within the mod
                foreach (var patch in lessMod.Patches)
                {
                    //If the swf hasn't been loaded, load it into the dictionary.
                    if (!swfs.ContainsKey(patch.Swf))
                    {
                        string fullPath = Path.Combine(lolLocation, patch.Swf);

                        //Backup the SWF
                        string   CurrentLocation = "";
                        string[] FileLocation    = patch.Swf.Split('/', '\\');
                        foreach (string s in FileLocation.Take(FileLocation.Length - 1))
                        {
                            CurrentLocation = Path.Combine(CurrentLocation, s);
                            if (!Directory.Exists(Path.Combine(lolLocation, "LESsBackup", BackupVersion, CurrentLocation)))
                            {
                                Directory.CreateDirectory(Path.Combine(lolLocation, "LESsBackup", BackupVersion, CurrentLocation));
                            }
                        }
                        if (!File.Exists(Path.Combine(lolLocation, "LESsBackup", BackupVersion, patch.Swf)))
                        {
                            File.Copy(Path.Combine(lolLocation, patch.Swf), Path.Combine(lolLocation, "LESsBackup", BackupVersion, patch.Swf));
                        }

                        swfs.Add(patch.Swf, SwfFile.ReadFile(fullPath));
                    }

                    //Get the SWF file that is being modified
                    SwfFile swf = swfs[patch.Swf];

                    if (patch.Action == "replace_swf_character")// replace an swf-character (buttons, sprites, fonts etc.)
                    {
                        ushort charId;
                        if (ushort.TryParse(patch.Class, out charId) && swf.CharacterTags.ContainsKey(charId))
                        {
                            swf.CharacterTags[charId].SetData(File.ReadAllBytes(Path.Combine(lessMod.Directory, patch.Code)));
                        }
                        else
                        {
                            _errorLevel = ErrorLevel.UnableToPatch;
                            throw new TraitNotFoundException($"<{patch.Class}> is not a valid Character ID.");
                        }
                    }
                    else
                    {
                        //Get the ABC tags (containing the code) from the swf file.
                        List <DoAbcTag> tags       = swf.GetDoAbcTags();
                        bool            classFound = false;
                        foreach (var tag in tags)
                        {
                            //check if this tag contains our script
                            ScriptInfo si = tag.GetScriptByClassName(patch.Class);

                            //check next tag if it doesn't
                            if (si == null)
                            {
                                continue;
                            }

                            ClassInfo cls = si.FindClass(patch.Class);
                            classFound = true;

                            Assembler asm;
                            //Perform the action based on what the patch defines
                            switch (patch.Action)
                            {
                            case "replace_trait":     //replace trait (method)
                                                      //Load the code from the patch and assemble it to be inserted into the code
                                asm = new Assembler(File.ReadAllText(Path.Combine(lessMod.Directory, patch.Code)));
                                TraitInfo newTrait = asm.Assemble() as TraitInfo;

                                int  traitIndex = cls.GetTraitIndexByTypeAndName(newTrait.Type, newTrait.Name.Name, Scope.Instance);
                                bool classTrait = false;
                                if (traitIndex < 0)
                                {
                                    traitIndex = cls.GetTraitIndexByTypeAndName(newTrait.Type, newTrait.Name.Name, Scope.Class);
                                    classTrait = true;
                                }
                                if (traitIndex < 0)
                                {
                                    throw new TraitNotFoundException(String.Format("Can't find trait \"{0}\" in class \"{1}\"", newTrait.Name.Name, patch.Class));
                                }

                                //Modified the found trait
                                if (classTrait)
                                {
                                    cls.ClassTraits[traitIndex] = newTrait;
                                }
                                else
                                {
                                    cls.InstanceTraits[traitIndex] = newTrait;
                                }
                                break;

                            case "replace_cinit":    //replace class constructor
                                                     //Load the code from the patch and assemble it to be inserted into the code
                                asm           = new Assembler(File.ReadAllText(Path.Combine(lessMod.Directory, patch.Code)));
                                cls.ClassInit = asm.Assemble() as MethodInfo;
                                break;

                            case "replace_iinit":    //replace instance constructor
                                                     //Load the code from the patch and assemble it to be inserted into the code
                                asm = new Assembler(File.ReadAllText(Path.Combine(lessMod.Directory, patch.Code)));
                                cls.InstanceInit = asm.Assemble() as MethodInfo;
                                break;

                            case "add_class_trait":     //add new class trait (method)
                                                        //Load the code from the patch and assemble it to be inserted into the code
                                asm        = new Assembler(File.ReadAllText(Path.Combine(lessMod.Directory, patch.Code)));
                                newTrait   = asm.Assemble() as TraitInfo;
                                traitIndex = cls.GetTraitIndexByTypeAndName(newTrait.Type, newTrait.Name.Name, Scope.Class);
                                if (traitIndex < 0)
                                {
                                    cls.ClassTraits.Add(newTrait);
                                }
                                else
                                {
                                    cls.ClassTraits[traitIndex] = newTrait;
                                }
                                break;

                            case "add_instance_trait":     //add new instance trait (method)
                                                           //Load the code from the patch and assemble it to be inserted into the code
                                asm        = new Assembler(File.ReadAllText(Path.Combine(lessMod.Directory, patch.Code)));
                                newTrait   = asm.Assemble() as TraitInfo;
                                traitIndex = cls.GetTraitIndexByTypeAndName(newTrait.Type, newTrait.Name.Name, Scope.Instance);
                                if (traitIndex < 0)
                                {
                                    cls.InstanceTraits.Add(newTrait);
                                }
                                else
                                {
                                    cls.InstanceTraits[traitIndex] = newTrait;
                                }
                                break;

                            case "remove_class_trait":
                                throw new NotImplementedException();

                            case "remove_instance_trait":
                                throw new NotImplementedException();

                            default:
                                throw new NotSupportedException($"Unknown Action \"{patch.Action}\" in mod {lessMod.Name}");
                            }
                        }
                        if (!classFound)
                        {
                            _errorLevel = ErrorLevel.UnableToPatch;
                            throw new ClassNotFoundException($"Class {patch.Class} not found in file {patch.Swf}");
                        }
                    }
                }
            }

            //Save the modified SWFS to their original location
            foreach (var patchedSwf in swfs)
            {
                try
                {
                    SetStatusLabelAsync("Applying mods: " + patchedSwf.Key);
                    string swfLoc = Path.Combine(lolLocation, patchedSwf.Key);
                    SwfFile.WriteFile(patchedSwf.Value, swfLoc);
                }
                catch
                {
                    _errorLevel = ErrorLevel.GoodJobYourInstallationIsProbablyCorruptedNow;
                    if (Debugger.IsAttached)
                    {
                        throw;
                    }
                }
            }
            timer.Stop();
        }