Fixed: in case there are other (non-map) lumps in the archive that have the same name as a map (e.g. MB2 patch and MB2 map in idl201x WADs) only the valid map is read.

This commit is contained in:
ZZYZX 2017-02-14 16:10:18 +02:00 committed by spherallic
parent 6bd76dee4e
commit 9054d07b9f
2 changed files with 38 additions and 26 deletions

View File

@ -1435,19 +1435,22 @@ namespace CodeImp.DoomBuilder
// [ZZ] this is the more specific case of MatchConfiguration from OpenMapOptionsForm.
// that code is not possible to reuse for this purpose though.
private int RemoveAllMapLumps(WAD target, string targetmapname)
private int FindAndRemoveMap(WAD target, string targetmapname, bool reallyremove)
{
int tgtheaderindex = -1;
int lastindex = -1;
bool writeheaders = false;
// [ZZ] Detect and delete target map from the target archive. Note that it can be in different format compared to current one, and there can be multiple maps with the same name as well.
//
while (true)
{
int nextindex = target.FindLumpIndex(targetmapname, tgtheaderindex);
// note that this (and the original algorithm too) would break if you have a patch or a texture named MAP01 for example...
int nextindex = target.FindLumpIndex(targetmapname, lastindex+1);
// note that the original algorithm would break if you have a patch or a texture named MAP01 for example...
// this is the case for multiple megawads that have level selection screen (Duel40-style), but luckily most of them are using the PK3 format.
// we are trying to detect if this is a valid map and shouldn't try to open or save over something that uses the map name as well.
if (nextindex < 0) break; // next lump not found
lastindex = nextindex;
// try to detect the format used for this map.
// if more than one format matches, do... idk what actually.
@ -1509,21 +1512,26 @@ namespace CodeImp.DoomBuilder
// if we didn't find anything it's weird...
if (trylist != null)
{
int checkindex = nextindex+1;
foreach (string lmp in trylist)
if (reallyremove)
{
if (checkindex >= target.Lumps.Count)
break;
bool match = trylist.Contains(target.Lumps[checkindex].Name);
if (match) target.RemoveAt(checkindex);
else break; // stop deleting on first non-matching lump
}
}
int checkindex = nextindex + 1;
foreach (string lmp in trylist)
{
if (checkindex >= target.Lumps.Count)
break;
bool match = trylist.Contains(target.Lumps[checkindex].Name);
if (match) target.RemoveAt(checkindex);
else break; // stop deleting on first non-matching lump
}
// how if trylist was not null, we need to remove the header as well.
target.RemoveAt(nextindex, false);
writeheaders = true;
tgtheaderindex = nextindex;
// now if trylist was not null, we need to remove the header as well.
target.RemoveAt(nextindex, false);
writeheaders = true;
lastindex--;
}
tgtheaderindex = nextindex;
}
}
if (writeheaders) target.WriteHeaders();
@ -1537,7 +1545,7 @@ namespace CodeImp.DoomBuilder
bool copynodebuild, bool copyscript,
bool deleteold = false) // [ZZ] deleteold=true means we need to delete the old map in-place. we only call this in SaveMap()
{
int tgtheaderindex = deleteold ? RemoveAllMapLumps(target, targetmapname) : target.FindLumpIndex(targetmapname);
int tgtheaderindex = FindAndRemoveMap(target, targetmapname, deleteold); // this is unobvious, but this function also performs search, not just deletion :)
bool replacetargetmap = !(deleteold && (tgtheaderindex > -1)); // this is unobvious, but we set replacetargetmap to false when we are completely overwriting it
if (tgtheaderindex == -1)
@ -1550,8 +1558,8 @@ namespace CodeImp.DoomBuilder
// Begin inserting at target header index
int targetindex = tgtheaderindex;
// Find the map header in source
int srcheaderindex = source.FindLumpIndex(sourcemapname);
// Find the map header in source
int srcheaderindex = FindAndRemoveMap(source, sourcemapname, false);
if(srcheaderindex > -1)
{
// Go for all the map lump names

View File

@ -297,10 +297,12 @@ namespace CodeImp.DoomBuilder.Windows
string selectedname = (mapslist.SelectedItems.Count > 0 ? mapslist.SelectedItems[0].Text : "");
// Make an array for the map names
List<ListViewItem> mapnames = new List<ListViewItem>();
//List<ListViewItem> mapnames = new List<ListViewItem>();
// [ZZ] This should be a string list so we can do mapnames.Contains
List<string> mapnames = new List<string>();
// Get selected configuration info
ConfigurationInfo ci = (config.SelectedItem as ConfigurationInfo);
// Get selected configuration info
ConfigurationInfo ci = (config.SelectedItem as ConfigurationInfo);
//mxd. Get configuration
Configuration cfg = ci.Configuration;
@ -351,16 +353,18 @@ namespace CodeImp.DoomBuilder.Windows
checkoffset++;
}
// Map found? Then add it to the list
if(lumpsfound >= lumpsrequired)
mapnames.Add(new ListViewItem(wadfile.Lumps[scanindex].Name));
// Map found? Then add it to the list
string mapname = wadfile.Lumps[scanindex].Name;
if ((lumpsfound >= lumpsrequired) && !mapnames.Contains(mapname))
mapnames.Add(mapname);
}
}
// Clear the list and add the new map names
mapslist.BeginUpdate();
mapslist.Items.Clear();
mapslist.Items.AddRange(mapnames.ToArray());
foreach (string mapname in mapnames)
mapslist.Items.Add(mapname);
mapslist.Sort();
// Go for all items in the list