mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-18 22:41:46 +00:00
Fixed: lump saving in script editor after editing archive with SLADE.\n Fixed: checking for concurrent modification in script editor while trying to save the lump.
This commit is contained in:
parent
a705e47fb9
commit
a5a942c798
8 changed files with 164 additions and 110 deletions
|
@ -98,33 +98,43 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
// Find lump, check it's hash
|
// Find lump, check it's hash
|
||||||
bool dosave = true;
|
bool dosave = true;
|
||||||
DataReader reader = source.Resource;
|
DataReader reader = source.Resource;
|
||||||
if(reader.FileExists(source.Filename, source.LumpIndex))
|
// reload the reader
|
||||||
{
|
bool wasReadOnly = reader.IsReadOnly;
|
||||||
using(MemoryStream ms = reader.LoadFile(source.Filename, source.LumpIndex))
|
reader.Reload(false);
|
||||||
{
|
try
|
||||||
if(MD5Hash.Get(ms) != hash
|
{
|
||||||
&& MessageBox.Show("Target lump was modified by another application. Do you still want to replace it?", "Warning", MessageBoxButtons.OKCancel)
|
if (reader.FileExists(source.Filename, source.LumpIndex))
|
||||||
== DialogResult.Cancel)
|
{
|
||||||
{
|
using (MemoryStream ms = reader.LoadFile(source.Filename, source.LumpIndex))
|
||||||
dosave = false;
|
{
|
||||||
}
|
if (MD5Hash.Get(ms) != hash
|
||||||
}
|
&& MessageBox.Show("Target lump was modified by another application. Do you still want to replace it?", "Warning", MessageBoxButtons.OKCancel)
|
||||||
}
|
== DialogResult.Cancel)
|
||||||
|
{
|
||||||
|
dosave = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(dosave)
|
if (dosave)
|
||||||
{
|
{
|
||||||
// Store the lump data
|
// Store the lump data
|
||||||
using(MemoryStream stream = new MemoryStream(editor.GetText()))
|
using (MemoryStream stream = new MemoryStream(editor.GetText()))
|
||||||
{
|
{
|
||||||
if(reader.SaveFile(stream, source.Filename, source.LumpIndex))
|
if (reader.SaveFile(stream, source.Filename, source.LumpIndex))
|
||||||
{
|
{
|
||||||
// Update what must be updated
|
// Update what must be updated
|
||||||
hash = MD5Hash.Get(stream);
|
hash = MD5Hash.Get(stream);
|
||||||
editor.SetSavePoint();
|
editor.SetSavePoint();
|
||||||
UpdateTitle();
|
UpdateTitle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
reader.Reload(wasReadOnly);
|
||||||
|
}
|
||||||
|
|
||||||
return dosave;
|
return dosave;
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,15 +141,27 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
// This suspends use of this resource
|
// This suspends use of this resource
|
||||||
public virtual void Suspend()
|
public virtual void Suspend()
|
||||||
{
|
{
|
||||||
|
// [ZZ] validate
|
||||||
|
if (issuspended) throw new Exception("Tried to suspend already suspended resource!");
|
||||||
issuspended = true;
|
issuspended = true;
|
||||||
|
isreadonly = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This resumes use of this resource
|
// This resumes use of this resource
|
||||||
public virtual void Resume()
|
public virtual void Resume()
|
||||||
{
|
{
|
||||||
issuspended = false;
|
// [ZZ] validate
|
||||||
|
if (!issuspended) throw new Exception("Tried to resume already resumed resource!");
|
||||||
|
issuspended = false;
|
||||||
|
isreadonly = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This reloads the resource (possibly as readonly).
|
||||||
|
public virtual void Reload(bool newreadonly)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ================== Palette
|
#region ================== Palette
|
||||||
|
|
|
@ -35,10 +35,10 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
{
|
{
|
||||||
#region ================== Variables
|
#region ================== Variables
|
||||||
|
|
||||||
private readonly DirectoryFilesList files;
|
private /*readonly*/ DirectoryFilesList files;
|
||||||
private IArchive archive; //mxd
|
private IArchive archive; //mxd
|
||||||
private readonly ArchiveType archivetype; //mxd
|
private /*readonly*/ ArchiveType archivetype; //mxd
|
||||||
private readonly Dictionary<string, byte[]> sevenzipentries; //mxd
|
private /*readonly*/ Dictionary<string, byte[]> sevenzipentries; //mxd
|
||||||
private bool bathmode = true; //mxd
|
private bool bathmode = true; //mxd
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -54,58 +54,63 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
// Constructor
|
// Constructor
|
||||||
public PK3Reader(DataLocation dl, bool asreadonly) : base(dl, asreadonly)
|
public PK3Reader(DataLocation dl, bool asreadonly) : base(dl, asreadonly)
|
||||||
{
|
{
|
||||||
General.WriteLogLine("Opening " + Path.GetExtension(location.location).ToUpper().Replace(".", "") + " resource \"" + location.location + "\"");
|
LoadFrom(dl, asreadonly);
|
||||||
|
|
||||||
if(!File.Exists(location.location))
|
|
||||||
throw new FileNotFoundException("Could not find the file \"" + location.location + "\"", location.location);
|
|
||||||
|
|
||||||
// Make list of all files
|
|
||||||
List<DirectoryFileEntry> fileentries = new List<DirectoryFileEntry>();
|
|
||||||
|
|
||||||
// Create archive
|
|
||||||
archive = ArchiveFactory.Open(location.location, Options.KeepStreamsOpen);
|
|
||||||
archivetype = archive.Type;
|
|
||||||
|
|
||||||
// Random access of 7z archives works TERRIBLY slow in SharpCompress
|
|
||||||
if(archivetype == ArchiveType.SevenZip)
|
|
||||||
{
|
|
||||||
isreadonly = true; // Unsaveable...
|
|
||||||
sevenzipentries = new Dictionary<string, byte[]>(StringComparer.Ordinal);
|
|
||||||
|
|
||||||
IReader reader = archive.ExtractAllEntries();
|
|
||||||
while(reader.MoveToNextEntry())
|
|
||||||
{
|
|
||||||
if(reader.Entry.IsDirectory || !CheckInvalidPathChars(reader.Entry.Key)) continue;
|
|
||||||
|
|
||||||
MemoryStream s = new MemoryStream();
|
|
||||||
reader.WriteEntryTo(s);
|
|
||||||
sevenzipentries.Add(reader.Entry.Key.ToLowerInvariant(), s.ToArray());
|
|
||||||
fileentries.Add(new DirectoryFileEntry(reader.Entry.Key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach(IArchiveEntry entry in archive.Entries)
|
|
||||||
{
|
|
||||||
if(!entry.IsDirectory && CheckInvalidPathChars(entry.Key))
|
|
||||||
fileentries.Add(new DirectoryFileEntry(entry.Key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get rid of archive
|
|
||||||
archive.Dispose();
|
|
||||||
archive = null;
|
|
||||||
|
|
||||||
// Make files list
|
|
||||||
files = new DirectoryFilesList(dl.GetDisplayName(), fileentries);
|
|
||||||
|
|
||||||
// Initialize without path (because we use paths relative to the PK3 file)
|
|
||||||
Initialize();
|
|
||||||
|
|
||||||
// We have no destructor
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LoadFrom(DataLocation dl, bool asreadonly)
|
||||||
|
{
|
||||||
|
General.WriteLogLine("Opening " + Path.GetExtension(location.location).ToUpper().Replace(".", "") + " resource \"" + location.location + "\"");
|
||||||
|
|
||||||
|
if (!File.Exists(location.location))
|
||||||
|
throw new FileNotFoundException("Could not find the file \"" + location.location + "\"", location.location);
|
||||||
|
|
||||||
|
// Make list of all files
|
||||||
|
List<DirectoryFileEntry> fileentries = new List<DirectoryFileEntry>();
|
||||||
|
|
||||||
|
// Create archive
|
||||||
|
archive = ArchiveFactory.Open(location.location, Options.KeepStreamsOpen);
|
||||||
|
archivetype = archive.Type;
|
||||||
|
|
||||||
|
// Random access of 7z archives works TERRIBLY slow in SharpCompress
|
||||||
|
if (archivetype == ArchiveType.SevenZip)
|
||||||
|
{
|
||||||
|
isreadonly = true; // Unsaveable...
|
||||||
|
sevenzipentries = new Dictionary<string, byte[]>(StringComparer.Ordinal);
|
||||||
|
|
||||||
|
IReader reader = archive.ExtractAllEntries();
|
||||||
|
while (reader.MoveToNextEntry())
|
||||||
|
{
|
||||||
|
if (reader.Entry.IsDirectory || !CheckInvalidPathChars(reader.Entry.Key)) continue;
|
||||||
|
|
||||||
|
MemoryStream s = new MemoryStream();
|
||||||
|
reader.WriteEntryTo(s);
|
||||||
|
sevenzipentries.Add(reader.Entry.Key.ToLowerInvariant(), s.ToArray());
|
||||||
|
fileentries.Add(new DirectoryFileEntry(reader.Entry.Key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (IArchiveEntry entry in archive.Entries)
|
||||||
|
{
|
||||||
|
if (!entry.IsDirectory && CheckInvalidPathChars(entry.Key))
|
||||||
|
fileentries.Add(new DirectoryFileEntry(entry.Key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get rid of archive
|
||||||
|
archive.Dispose();
|
||||||
|
archive = null;
|
||||||
|
|
||||||
|
// Make files list
|
||||||
|
files = new DirectoryFilesList(dl.GetDisplayName(), fileentries);
|
||||||
|
|
||||||
|
// Initialize without path (because we use paths relative to the PK3 file)
|
||||||
|
Initialize();
|
||||||
|
|
||||||
|
// We have no destructor
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
// Disposer
|
// Disposer
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
|
@ -149,12 +154,25 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ================== Textures
|
#region ================== Management
|
||||||
|
|
||||||
// This finds and returns a patch stream
|
// [ZZ]
|
||||||
public override Stream GetPatchData(string pname, bool longname, ref string patchlocation)
|
// This reloads the resource
|
||||||
|
public override void Reload(bool newreadonly)
|
||||||
|
{
|
||||||
|
if (archive != null)
|
||||||
|
archive.Dispose();
|
||||||
|
LoadFrom(location, newreadonly);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Textures
|
||||||
|
|
||||||
|
// This finds and returns a patch stream
|
||||||
|
public override Stream GetPatchData(string pname, bool longname, ref string patchlocation)
|
||||||
{
|
{
|
||||||
// Error when suspended
|
// Error when suspended
|
||||||
if(issuspended) throw new Exception("Data reader is suspended");
|
if(issuspended) throw new Exception("Data reader is suspended");
|
||||||
|
|
|
@ -72,8 +72,10 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
// Call this to initialize this class
|
// Call this to initialize this class
|
||||||
protected virtual void Initialize()
|
protected virtual void Initialize()
|
||||||
{
|
{
|
||||||
// Load all WAD files in the root as WAD resources
|
// [ZZ] we can have wad files already. dispose if any.
|
||||||
string[] wadfiles = GetWadFiles();
|
if (wads != null) foreach (WADReader wr in wads) wr.Dispose();
|
||||||
|
// Load all WAD files in the root as WAD resources
|
||||||
|
string[] wadfiles = GetWadFiles();
|
||||||
wads = new List<WADReader>(wadfiles.Length);
|
wads = new List<WADReader>(wadfiles.Length);
|
||||||
foreach(string w in wadfiles)
|
foreach(string w in wadfiles)
|
||||||
{
|
{
|
||||||
|
@ -114,13 +116,13 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
foreach(WADReader wr in wads) wr.Resume();
|
foreach(WADReader wr in wads) wr.Resume();
|
||||||
base.Resume();
|
base.Resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ================== Palette
|
|
||||||
|
|
||||||
// This loads the PLAYPAL palette
|
#endregion
|
||||||
public override Playpal LoadPalette()
|
|
||||||
|
#region ================== Palette
|
||||||
|
|
||||||
|
// This loads the PLAYPAL palette
|
||||||
|
public override Playpal LoadPalette()
|
||||||
{
|
{
|
||||||
// Error when suspended
|
// Error when suspended
|
||||||
if(issuspended) throw new Exception("Data reader is suspended");
|
if(issuspended) throw new Exception("Data reader is suspended");
|
||||||
|
|
|
@ -211,19 +211,28 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
public override void Suspend()
|
public override void Suspend()
|
||||||
{
|
{
|
||||||
file.Dispose();
|
file.Dispose();
|
||||||
|
file = null;
|
||||||
base.Suspend();
|
base.Suspend();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This resumes use of this resource
|
// This resumes use of this resource
|
||||||
public override void Resume()
|
public override void Resume()
|
||||||
{
|
{
|
||||||
file = new WAD(location.location, true);
|
Reload(true);
|
||||||
is_iwad = file.IsIWAD;
|
|
||||||
base.Resume();
|
base.Resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This fills a ranges list
|
// This reloads the resource
|
||||||
private void FindRanges(List<LumpRange> ranges, IDictionary rangeinfos, string rangename, string elementname)
|
public override void Reload(bool newreadonly)
|
||||||
|
{
|
||||||
|
if (file != null) file.Dispose();
|
||||||
|
file = new WAD(location.location, newreadonly);
|
||||||
|
is_iwad = file.IsIWAD;
|
||||||
|
base.Reload(newreadonly);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This fills a ranges list
|
||||||
|
private void FindRanges(List<LumpRange> ranges, IDictionary rangeinfos, string rangename, string elementname)
|
||||||
{
|
{
|
||||||
Dictionary<LumpRange, KeyValuePair<string, string>> failedranges = new Dictionary<LumpRange, KeyValuePair<string, string>>(); //mxd
|
Dictionary<LumpRange, KeyValuePair<string, string>> failedranges = new Dictionary<LumpRange, KeyValuePair<string, string>>(); //mxd
|
||||||
Dictionary<int, bool> successfulrangestarts = new Dictionary<int, bool>(); //mxd
|
Dictionary<int, bool> successfulrangestarts = new Dictionary<int, bool>(); //mxd
|
||||||
|
@ -1169,16 +1178,16 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
if(isreadonly || lumpindex < 0 || file.Lumps.Count <= lumpindex || file.Lumps[lumpindex].Name != lumpname.ToUpperInvariant())
|
if(isreadonly || lumpindex < 0 || file.Lumps.Count <= lumpindex || file.Lumps[lumpindex].Name != lumpname.ToUpperInvariant())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Remove the lump
|
// Remove the lump
|
||||||
file.RemoveAt(lumpindex);
|
file.RemoveAt(lumpindex);
|
||||||
|
|
||||||
// Insert new lump
|
// Insert new lump
|
||||||
Lump l = file.Insert(lumpname, lumpindex, (int)lumpdata.Length);
|
Lump l = file.Insert(lumpname, lumpindex, (int)lumpdata.Length);
|
||||||
l.Stream.Seek(0, SeekOrigin.Begin);
|
l.Stream.Seek(0, SeekOrigin.Begin);
|
||||||
lumpdata.WriteTo(l.Stream);
|
lumpdata.WriteTo(l.Stream);
|
||||||
|
|
||||||
// Update WAD file
|
// Update WAD file
|
||||||
file.WriteHeaders();
|
file.WriteHeaders();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,6 @@ using CodeImp.DoomBuilder;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("2.3.0.2837")]
|
[assembly: AssemblyVersion("2.3.0.2839")]
|
||||||
[assembly: NeutralResourcesLanguageAttribute("en")]
|
[assembly: NeutralResourcesLanguageAttribute("en")]
|
||||||
[assembly: AssemblyHash("30a5edf")]
|
[assembly: AssemblyHash("a705e47")]
|
||||||
|
|
|
@ -211,9 +211,12 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//mxd. Bail out if still no dice...
|
// [ZZ] dispose of wadfile
|
||||||
if(config.SelectedIndex == -1 || mapslist.Items.Count == 0)
|
wadfile.Dispose();
|
||||||
|
|
||||||
|
//mxd. Bail out if still no dice...
|
||||||
|
if (config.SelectedIndex == -1 || mapslist.Items.Count == 0)
|
||||||
{
|
{
|
||||||
General.ShowWarningMessage("Unable to find maps using any game configuration.\nDoes this wad contain any maps at all?..", MessageBoxButtons.OK);
|
General.ShowWarningMessage("Unable to find maps using any game configuration.\nDoes this wad contain any maps at all?..", MessageBoxButtons.OK);
|
||||||
cancel_Click(this, EventArgs.Empty);
|
cancel_Click(this, EventArgs.Empty);
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Resources;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("2.3.0.2837")]
|
[assembly: AssemblyVersion("2.3.0.2839")]
|
||||||
[assembly: NeutralResourcesLanguageAttribute("en")]
|
[assembly: NeutralResourcesLanguageAttribute("en")]
|
||||||
|
|
Loading…
Reference in a new issue