Refactor DBPFFile Changes system.

This commit is contained in:
LazyDuchess 2023-01-20 18:00:39 -03:00
parent 534f5153b2
commit a0350dbe37
18 changed files with 271 additions and 174 deletions

View file

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 3e726922005148344b00350b40b263f9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,18 +0,0 @@
using OpenTS2.Common;
using OpenTS2.Files.Formats.DBPF;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenTS2.Content.Changes
{
public abstract class AbstractChanged
{
public virtual bool Compressed { get; set; } = false;
public virtual AbstractAsset Asset { get; set; }
public virtual byte[] Bytes { get; set; }
public DBPFEntry Entry;
}
}

View file

@ -1,47 +0,0 @@
using OpenTS2.Common;
using OpenTS2.Files.Formats.DBPF;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenTS2.Content.Changes
{
public class ChangedAsset : AbstractChanged
{
public override bool Compressed
{
get
{
return Asset.Compressed;
}
}
public AbstractCodec Codec;
public override byte[] Bytes
{
get
{
return Codec.Serialize(Asset);
}
set
{
throw new NotSupportedException();
}
}
public ChangedAsset(AbstractAsset asset, AbstractCodec codec)
{
this.Asset = asset;
this.Codec = codec;
this.Entry = new DynamicDBPFEntry()
{
Dynamic = true,
Change = this,
Package = asset.Package
};
}
public ChangedAsset(AbstractAsset asset) : this(asset, Codecs.Get(asset.GlobalTGI.TypeID))
{
}
}
}

View file

@ -1,45 +0,0 @@
using OpenTS2.Common;
using OpenTS2.Files.Formats.DBPF;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenTS2.Content.Changes
{
public class ChangedFile : AbstractChanged
{
protected byte[] FileData;
public ChangedFile(byte[] fileData, ResourceKey tgi, DBPFFile package, AbstractCodec codec = null)
{
this.FileData = fileData;
if (codec != null)
{
this.Asset = codec.Deserialize(fileData, tgi, package);
}
this.Entry = new DBPFEntry()
{
TGI = tgi,
Dynamic = true,
Package = package,
FileSize = (uint)FileData.Length
};
}
public ChangedFile(AbstractAsset asset, byte[] fileData) : this(fileData, asset.TGI, asset.Package)
{
}
public override byte[] Bytes
{
get
{
return FileData;
}
set
{
FileData = value;
}
}
}
}

View file

@ -0,0 +1,23 @@
using OpenTS2.Common;
using OpenTS2.Content;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenTS2.Files.Formats.DBPF
{
/// <summary>
/// Holds the actual data of a changed DBPF Resource.
/// </summary>
public abstract class ChangedResourceData
{
public abstract byte[] GetBytes();
public abstract AbstractAsset GetAsset();
public T GetAsset<T>() where T : AbstractAsset
{
return GetAsset() as T;
}
}
}

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: c9172137a3e04d94a8c0b1b1a27edab8
guid: 9ce532cab413ed848bc2c67e759cf77b
MonoImporter:
externalObjects: {}
serializedVersion: 2

View file

@ -0,0 +1,34 @@
using OpenTS2.Common;
using OpenTS2.Content;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenTS2.Files.Formats.DBPF
{
/// <summary>
/// Holds the data for a changed DBPF Asset.
/// </summary>
public class ChangedResourceDataAsset : ChangedResourceData
{
private AbstractAsset _asset;
private AbstractCodec _codec;
public ChangedResourceDataAsset(AbstractAsset asset, AbstractCodec codec = null)
{
this._asset = asset;
this._codec = codec;
}
public override byte[] GetBytes()
{
if (_codec == null)
return null;
return _codec.Serialize(_asset);
}
public override AbstractAsset GetAsset()
{
return _asset;
}
}
}

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 5d06b08c07f2788459a67e4e585b06bc
guid: 8ac992f51649ec3419c2f9ec0dcbc533
MonoImporter:
externalObjects: {}
serializedVersion: 2

View file

@ -0,0 +1,38 @@
using OpenTS2.Common;
using OpenTS2.Content;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenTS2.Files.Formats.DBPF
{
/// <summary>
/// Holds the bytes for a changed DBPF Asset.
/// </summary>
public class ChangedResourceDataBytes : ChangedResourceData
{
private byte[] _bytes;
private AbstractCodec _codec;
private ResourceKey _tgi;
private DBPFFile _package;
public ChangedResourceDataBytes(byte[] bytes, ResourceKey tgi, AbstractCodec codec = null, DBPFFile package = null)
{
this._bytes = bytes;
this._tgi = tgi;
this._codec = codec;
this._package = package;
}
public override byte[] GetBytes()
{
return _bytes;
}
public override AbstractAsset GetAsset()
{
if (_codec == null)
return null;
return _codec.Deserialize(_bytes, _tgi, _package);
}
}
}

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 38768ce194829694f83a97a94de3c8dd
guid: 9bdbc86ecf0a3a743b3171f96f511e00
MonoImporter:
externalObjects: {}
serializedVersion: 2

View file

@ -0,0 +1,31 @@
using OpenTS2.Common;
using OpenTS2.Content;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenTS2.Files.Formats.DBPF
{
/// <summary>
/// Returns data from an entry for a changed DBPF asset.
/// </summary>
public class ChangedResourceDataEntry : ChangedResourceData
{
private DBPFEntry _dbpfEntry;
public ChangedResourceDataEntry(DBPFEntry entry)
{
this._dbpfEntry = entry;
}
public override byte[] GetBytes()
{
return _dbpfEntry.GetBytes();
}
public override AbstractAsset GetAsset()
{
return _dbpfEntry.GetAsset();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c01207b759015314d99451fea61faf61
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,23 @@
using OpenTS2.Common;
using OpenTS2.Content;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenTS2.Files.Formats.DBPF
{
/// <summary>
/// Holds the metadata of a changed DBPF Resource.
/// </summary>
public class ChangedResourceMetadata
{
public ChangedResourceData Data = null;
public bool Compressed = false;
public ChangedResourceMetadata()
{
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 14b73daa80ddb7441b4d529b32526b1f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -10,7 +10,6 @@ using System.Linq;
using System.Text;
using OpenTS2.Common;
using OpenTS2.Content;
using OpenTS2.Content.Changes;
namespace OpenTS2.Files.Formats.DBPF
{
@ -58,7 +57,7 @@ namespace OpenTS2.Files.Formats.DBPF
/// <summary>
/// Global TGI.
/// </summary>
public virtual ResourceKey GlobalTGI
public ResourceKey GlobalTGI
{
get
{
@ -71,7 +70,7 @@ namespace OpenTS2.Files.Formats.DBPF
/// <summary>
/// Internal TGI, relative to parent package.
/// </summary>
public virtual ResourceKey TGI { get; set; } = ResourceKey.Default;
public ResourceKey TGI { get; set; } = ResourceKey.Default;
//A 4-byte unsigned integer specifying the offset to the entry's data from the beginning of the archive
public uint FileOffset;
@ -79,10 +78,9 @@ namespace OpenTS2.Files.Formats.DBPF
//A 4-byte unsigned integer specifying the size of the entry's data
public virtual uint FileSize { get; set; }
public bool Dynamic = false;
public DBPFFile Package;
public byte[] GetBytes()
public virtual byte[] GetBytes()
{
return Package.GetBytes(this);
}
@ -92,38 +90,9 @@ namespace OpenTS2.Files.Formats.DBPF
return GetAsset() as T;
}
public AbstractAsset GetAsset()
public virtual AbstractAsset GetAsset()
{
return Package.GetAsset(this);
}
}
public class DynamicDBPFEntry : DBPFEntry
{
public override ResourceKey GlobalTGI
{
get
{
return Change.Asset.GlobalTGI;
}
}
public override ResourceKey TGI
{
get
{
return Change.Asset.TGI;
}
set
{
Change.Asset.TGI = value;
}
}
public ChangedAsset Change;
public override uint FileSize {
get
{
return (uint)Change.Bytes.Length;
}
}
}
}

View file

@ -13,7 +13,6 @@ using OpenTS2.Files.Utils;
using OpenTS2.Common;
using OpenTS2.Common.Utils;
using OpenTS2.Content;
using OpenTS2.Content.Changes;
using OpenTS2.Content.DBPF;
namespace OpenTS2.Files.Formats.DBPF
@ -38,7 +37,7 @@ namespace OpenTS2.Files.Formats.DBPF
public bool Dirty = false;
public Dictionary<ResourceKey, bool> DeletedEntries = new Dictionary<ResourceKey, bool>();
public Dictionary<ResourceKey, AbstractChanged> ChangedEntries = new Dictionary<ResourceKey, AbstractChanged>();
public Dictionary<ResourceKey, DynamicDBPFEntry> ChangedEntries = new Dictionary<ResourceKey, DynamicDBPFEntry>();
public DBPFFileChanges(DBPFFile owner)
{
@ -156,11 +155,18 @@ namespace OpenTS2.Files.Formats.DBPF
public void Set(AbstractAsset asset)
{
asset.Package = _owner;
var changedAsset = new ChangedAsset(asset);
ChangedEntries[asset.TGI] = changedAsset;
if (!ChangedEntries.TryGetValue(asset.TGI, out DynamicDBPFEntry changedEntry))
changedEntry = new DynamicDBPFEntry();
changedEntry.Package = _owner;
changedEntry.TGI = asset.TGI;
var changedAsset = new ChangedResourceDataAsset(asset, Codecs.Get(asset.TGI.TypeID));
changedEntry.Change.Data = changedAsset;
changedEntry.Change.Compressed = asset.Compressed;
ChangedEntries[asset.TGI] = changedEntry;
InternalRestore(asset.TGI);
Dirty = true;
Provider?.UpdateOrAddToResourceMap(changedAsset.Entry);
Provider?.UpdateOrAddToResourceMap(changedEntry);
RefreshCache(asset.TGI);
}
/// <summary>
@ -171,14 +177,37 @@ namespace OpenTS2.Files.Formats.DBPF
/// <param name="compressed">Compress?</param>
public void Set(byte[] bytes, ResourceKey tgi, bool compressed)
{
var changedFile = new ChangedFile(bytes, tgi, _owner, Codecs.Get(tgi.TypeID))
{
Compressed = compressed
};
ChangedEntries[tgi] = changedFile;
var changedData = new ChangedResourceDataBytes(bytes, tgi, Codecs.Get(tgi.TypeID), _owner);
if (!ChangedEntries.TryGetValue(tgi, out DynamicDBPFEntry changedEntry))
changedEntry = new DynamicDBPFEntry();
changedEntry.TGI = tgi;
changedEntry.Change.Data = changedData;
changedEntry.Change.Compressed = compressed;
ChangedEntries[tgi] = changedEntry;
InternalRestore(tgi);
Dirty = true;
Provider?.UpdateOrAddToResourceMap(changedFile.Entry);
Provider?.UpdateOrAddToResourceMap(changedEntry);
RefreshCache(tgi);
}
/// <summary>
/// Sets compression for a resource.
/// </summary>
/// <param name="tgi">Resource TGI.</param>
/// <param name="compressed">Compress?</param>
public void SetCompressed(ResourceKey tgi, bool compressed)
{
if (!ChangedEntries.TryGetValue(tgi, out DynamicDBPFEntry changedEntry))
{
changedEntry = new DynamicDBPFEntry();
changedEntry.Change.Data = new ChangedResourceDataEntry(_owner.GetEntryByTGI(tgi));
}
changedEntry.TGI = tgi;
changedEntry.Change.Compressed = compressed;
ChangedEntries[tgi] = changedEntry;
InternalRestore(tgi);
Dirty = true;
Provider?.UpdateOrAddToResourceMap(changedEntry);
RefreshCache(tgi);
}
}
@ -260,7 +289,7 @@ namespace OpenTS2.Files.Formats.DBPF
}
foreach(var element in Changes.ChangedEntries)
{
finalEntries.Add(element.Value.Entry);
finalEntries.Add(element.Value);
}
return finalEntries;
}
@ -494,7 +523,7 @@ namespace OpenTS2.Files.Formats.DBPF
writer.Write((int)filePosition);
wStream.Position = filePosition;
var entry = entries[i];
var entryData = GetBytes(entry);
var entryData = entry.GetBytes();
if (dirAsset != null && dirAsset.GetUncompressedSize(entry.TGI) != 0)
{
entryData = DBPFCompression.Compress(entryData);
@ -525,7 +554,7 @@ namespace OpenTS2.Files.Formats.DBPF
if (element is DynamicDBPFEntry dynamicEntry)
{
if (dynamicEntry.Change.Compressed)
dirAsset.SizeByInternalTGI[element.TGI] = (uint)dynamicEntry.Change.Bytes.Length;
dirAsset.SizeByInternalTGI[element.TGI] = (uint)dynamicEntry.FileSize;
}
else
{
@ -558,7 +587,7 @@ namespace OpenTS2.Files.Formats.DBPF
return null;
}
if (Changes.ChangedEntries.ContainsKey(entry.TGI))
return Changes.ChangedEntries[entry.TGI].Bytes;
return Changes.ChangedEntries[entry.TGI].Change.Data.GetBytes();
_reader.Seek(SeekOrigin.Begin, entry.FileOffset);
var fileBytes = _reader.ReadBytes((int)entry.FileSize);
var uncompressedSize = InternalGetUncompressedSize(entry);
@ -582,7 +611,7 @@ namespace OpenTS2.Files.Formats.DBPF
return null;
}
if (Changes.ChangedEntries.ContainsKey(tgi))
return Changes.ChangedEntries[tgi].Bytes;
return Changes.ChangedEntries[tgi].Change.Data.GetBytes();
if (_entryByTGI.ContainsKey(tgi))
return GetBytes(_entryByTGI[tgi]);
else
@ -621,7 +650,7 @@ namespace OpenTS2.Files.Formats.DBPF
if (Changes.DeletedEntries.ContainsKey(entry.TGI) && ignoreDeleted)
return null;
if (Changes.ChangedEntries.ContainsKey(entry.TGI))
return Changes.ChangedEntries[entry.TGI].Asset;
return Changes.ChangedEntries[entry.TGI].Change.Data.GetAsset();
var item = GetBytes(entry, ignoreDeleted);
var codec = Codecs.Get(entry.GlobalTGI.TypeID);
var asset = codec.Deserialize(item, entry.GlobalTGI, this);
@ -631,6 +660,11 @@ namespace OpenTS2.Files.Formats.DBPF
return asset;
}
public bool IsCompressed(DBPFEntry entry)
{
return InternalGetUncompressedSize(entry) > 0;
}
public T GetAssetByTGI<T>(ResourceKey tgi, bool ignoreDeleted = true) where T : AbstractAsset
{
return GetAssetByTGI(tgi, ignoreDeleted) as T;
@ -654,7 +688,7 @@ namespace OpenTS2.Files.Formats.DBPF
if (Changes.DeletedEntries.ContainsKey(tgi) && ignoreDeleted)
return null;
if (Changes.ChangedEntries.ContainsKey(tgi))
return Changes.ChangedEntries[tgi].Entry;
return Changes.ChangedEntries[tgi];
if (_entryByTGI.ContainsKey(tgi))
return _entryByTGI[tgi];
else

View file

@ -0,0 +1,30 @@
using OpenTS2.Content;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenTS2.Files.Formats.DBPF
{
public class DynamicDBPFEntry : DBPFEntry
{
public ChangedResourceMetadata Change = new ChangedResourceMetadata();
public override uint FileSize
{
get
{
return (uint)Change.Data.GetBytes().Length;
}
}
public override byte[] GetBytes()
{
return Change.Data.GetBytes();
}
public override AbstractAsset GetAsset()
{
return Change.Data.GetAsset();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f874050d3fe59bf4cb0f5d8573cb6520
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: