예제 #1
0
        public void PatchDirArchive(ModData mod, string archivepath)
        {
            string archive_dir = mod.Path + archivepath;

            // Check if the mod has a directory for wad resources
            if (Directory.Exists(archive_dir))
            {
                Archive archive = new Archive(TempPath + archivepath + ".wad");
                archive.Load();

                int i, j;
                int count = 0;

                // Go through the groups in the archive file.
                for (i = 0; i < archive.Groups.Count; i++)
                {
                    var group = archive.Groups[i];

                    //Check for matching subdirectory and archive group.
                    if (Directory.Exists(archive_dir + "/" + group.Name))
                    {
                        //Go through the entries in the archive file
                        for (j = 0; j < archive.Groups[i].Entries.Count; j++)
                        {
                            var entry = archive.Groups[i].Entries[j];

                            //Check for matching file and archive entry.
                            string filepath = archive_dir + "/" + group.Name + "/" + entry.Name;
                            if (File.Exists(filepath))
                            {
                                Byte[] data = File.ReadAllBytes(filepath);
                                var new_entry = new Entry(entry.Name, data);

                                //Replace entry in the archive.wad with file in mod archive folder.
                                archive.Groups[i].Entries[j] = new_entry;

                                //Msg.Log("Patching '" + group.Name + "/" + entry.Name + "' from " + mod.Name);
                                count++;
                            }
                        }
                    }
                }

                archive.Save();

                if (count > 0) Msg.Log("Patched " + count + " " + archivepath + " resources for " + mod.Name);
            }
        }
예제 #2
0
        // Patch the game files
        public bool PatchGame(bool reset_only)
        {
            Settings settings = Program.mainForm.Settings;
            ModManager modMan = Program.mainForm.ModMan;
            SkinManager skinMan = Program.mainForm.SkinMan;
            
            string message;

            if (CheckGameDir() == false)
            {
                message = "The Spelunky directory is not set!" +
                    Environment.NewLine + Environment.NewLine +
                "Patchlunky cannot patch the game until the directory is set.";
                Msg.MsgBox(message, "Patchlunky Setup");
                return false; //Path to game has not been set, can't patch.
            }

            if (CheckBackups() == false)
            {
                message = "Patchlunky is missing Spelunky backups!" +
                    Environment.NewLine + Environment.NewLine +
                "Patchlunky cannot patch the game without backups.";
                Msg.MsgBox(message, "Patchlunky Setup");
                return false; //Backups are missing, can't patch.
            }

            Program.mainForm.SetProgress(0);

            // STEP 1 OF 4 - Copy default data files to temp folder
            foreach (GameFile gmfile in DefaultFiles)
            {
                try
                {
                    string srcfile = this.BackupPath + gmfile.FilePath;
                    string dstfile = this.TempPath + gmfile.FilePath;
                    Directory.CreateDirectory(Path.GetDirectoryName(dstfile));
                    File.Copy(srcfile, dstfile, true);
                }
                catch (Exception ex)
                {
                    Msg.MsgBox("Error trying to copy file: " + ex.Message, "Patchlunky Setup");
                    return false; //Stop patching
                }
            }

            Program.mainForm.SetProgress(33);

            // STEP 2 OF 4 - Copy mod files to temp folder
            if ((reset_only == false) && (modMan.Mods.Count > 0))
            {
                foreach (ModData mod in modMan.Mods)
                {
                    if (mod.Enabled == false)
                        continue;

                    //Patch game files in the mod.
                    if (PatchFiles(mod) == false)
                        return false; //Stop patching

                    //Patch wad resources in the mod.
                    PatchArchive(mod, "Textures/alltex");
                    PatchArchive(mod, "Sounds/allsounds");
                }
            }

            // STEP 3 OF 4 - Patch alltex.wad in temp folder with skin files
            if ((reset_only == false) && (skinMan.SkinConfig.Count > 0))
            {
                Archive archive = new Archive(TempPath + "Textures/alltex" + ".wad");
                archive.Load();

                int i = archive.Groups.FindIndex(o => o.Name.Equals("PLAYERS", StringComparison.OrdinalIgnoreCase));
                if (i == -1)
                    return false; //Missing "PLAYERS" group in archive, stop patching                

                int count = 0;

                foreach(KeyValuePair<string, string> kvp in skinMan.SkinConfig)
                {
                    SkinData oldSkin = skinMan.GetSkin(kvp.Key);
                    SkinData newSkin = skinMan.GetSkin(kvp.Value);

                    bool skinsMatch = kvp.Key.Equals(kvp.Value);

                    if (skinsMatch && settings.Check("ModsReplaceDefaultSkins", "True"))
                        continue; //Skip default skins

                    int j = archive.Groups[i].Entries.FindIndex(o => o.Name.Equals(oldSkin.Name + ".png", StringComparison.OrdinalIgnoreCase));
                    if (j == -1)
                        continue; //Skip missing character entry

                    Byte[] data = File.ReadAllBytes(newSkin.Path);
                    var new_entry = new Entry(oldSkin.Name + ".png", data);

                    //Replace entry in the archive.wad
                    archive.Groups[i].Entries[j] = new_entry;
                    //Msg.Log("Patching skin '" + oldSkin.Name + " to '" + newSkin.Name + "'.");

                    if (skinsMatch == false)
                        count++;
                }

                if (count > 0) Msg.Log("Patched " + count + " character skins");

                archive.Save();
            }

            Program.mainForm.SetProgress(66);

            // STEP 4 OF 4 - Copy files to Spelunky data folders.
            foreach (GameFile gmfile in DefaultFiles)
            {
                try
                {
                    string srcfile = this.TempPath + gmfile.FilePath;
                    string dstfile = this.GamePath + "Data/" + gmfile.FilePath;
                    File.Copy(srcfile, dstfile, true);
                }
                catch (Exception ex)
                {
                    Msg.MsgBox("Error patching file: " + ex.Message, "Patchlunky Setup");
                    return false; //Stop patching
                }
            }

            Program.mainForm.SetProgress(100);

            return true;
        }
예제 #3
0
        public void PatchZipArchive(ModData mod, string archivepath)
        {
            ZipFile zip = new ZipFile(mod.Path);

            // Check if the mod has a directory for wad resources
            if (zip.ContainsEntry(archivepath + "/"))
            {
                Archive archive = new Archive(TempPath + archivepath + ".wad");
                archive.Load();

                int i, j;
                int count = 0;

                // Go through the groups in the archive file.
                for (i = 0; i < archive.Groups.Count; i++)
                {
                    var group = archive.Groups[i];

                    //Check for matching subdirectory and archive group.
                    string grouppath = archivepath + "/" + group.Name + "/";
                    if (zip.ContainsEntry(grouppath))
                    {
                        //Go through the entries in the archive file
                        for (j = 0; j < archive.Groups[i].Entries.Count; j++)
                        {
                            var entry = archive.Groups[i].Entries[j];

                            //Check for matching file and archive entry.
                            string entrypath = grouppath + entry.Name;
                            if (zip.ContainsEntry(entrypath))
                            {
                                //Msg.Log("zip: " + mod.Name + ", matching res-entry: " + entrypath);

                                MemoryStream stream = new MemoryStream();
                                zip[entrypath].Extract(stream);

                                Byte[] data = stream.GetBuffer();
                                var new_entry = new Entry(entry.Name, data);

                                //Replace entry in the archive.wad with file in mod archive folder.
                                archive.Groups[i].Entries[j] = new_entry;
                                //Msg.Log("Patching '" + group.Name + "/" + entry.Name + "' from zip " + mod.Name);
                                count++;
                            }
                        }
                    }
                }
                archive.Save();

                if (count > 0) Msg.Log("Patched " + count + " " + archivepath + " resources for " + mod.Name);
            }            
        }
예제 #4
0
		/// <summary>
		/// Loads this WAD archive from file.
		/// </summary>
		public void Load()
		{
			//context
			var groups = new List<Group>();
			Group group = null;

			using (FileStream wadStream = File.Open(this.WadFile, FileMode.Open))
			using (StreamReader wixStreamReader = new StreamReader(File.Open(this.WixFile, FileMode.Open)))
			{
				while (!wixStreamReader.EndOfStream)
				{
					//read
					var line = wixStreamReader.ReadLine();
					var parts = line.Split(' ');
					var identifier = parts[0];

					switch (identifier)
					{
						case "!group":
						{
							if (group != null)
							{
								//add
								groups.Add(group);
							}

							//group
							var name = parts[1];

							//create
							group = new Group(name);

							break;
						}
						default:
						{
							//entry
							var name = parts[0];
							var offset = int.Parse(parts[1]);
							var length = int.Parse(parts[2]);

							//data
							var data = new byte[length];
							wadStream.Seek(offset, SeekOrigin.Begin);
							wadStream.Read(data, 0, length);

							//create
							var entry = new Entry(name, data);
							group.Entries.Add(entry);

							break;
						}
					}
				}

				if (group != null)
				{
					//add last
					groups.Add(group);
				}
			}

			//set
			this.Groups = groups;
		}