Some code cleanup.
parent
5582debcee
commit
f67b95007a
|
@ -1,5 +1,4 @@
|
||||||
|
using System;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -12,18 +11,68 @@ namespace GarrysMod.AddonCreator
|
||||||
{
|
{
|
||||||
public class Addon
|
public class Addon
|
||||||
{
|
{
|
||||||
private static readonly byte[] FormatIdent = Encoding.ASCII.GetBytes("GMAD");
|
|
||||||
private const byte FormatVersion = 3;
|
private const byte FormatVersion = 3;
|
||||||
private const uint AppID = 4000;
|
private const uint AppID = 4000;
|
||||||
private const uint CompressionSignature = 0xbeefcace;
|
private const uint CompressionSignature = 0xbeefcace;
|
||||||
|
private static readonly byte[] FormatIdent = Encoding.ASCII.GetBytes("GMAD");
|
||||||
|
|
||||||
public static void CreateFromFolder()
|
/// <summary>
|
||||||
|
/// Initializes a new instance of <see cref="Addon" />
|
||||||
|
/// </summary>
|
||||||
|
public Addon()
|
||||||
{
|
{
|
||||||
|
Files = new Dictionary<string, AddonFileInfo>();
|
||||||
|
RequiredContent = new List<string>();
|
||||||
|
Version = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Imports a gmod addon into this instance.
|
/// Returns the timestamp of when the addon was built. This data is retrieved from full imports and for new (unsaved)
|
||||||
|
/// addons this is 0.
|
||||||
|
/// </summary>
|
||||||
|
public ulong BuildTimestamp { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of this addon.
|
||||||
|
/// </summary>
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The author of this addon.
|
||||||
|
/// </summary>
|
||||||
|
public string Author { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A description of this addon.
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This addon's version.
|
||||||
|
/// </summary>
|
||||||
|
public int Version { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The files to include in the addon.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, AddonFileInfo> Files { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Currently unused.
|
||||||
|
/// </summary>
|
||||||
|
public ulong SteamID { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Content that needs to exist in order to run this addon.
|
||||||
|
/// </summary>
|
||||||
|
public List<string> RequiredContent { get; private set; }
|
||||||
|
|
||||||
|
public static void CreateFromFolder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Imports a gmod addon into this instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">Path to a gmod addon file.</param>
|
/// <param name="path">Path to a gmod addon file.</param>
|
||||||
/// <param name="withMetadata">Import all metadata (title, description, creator, timestamp, etc.) as well?</param>
|
/// <param name="withMetadata">Import all metadata (title, description, creator, timestamp, etc.) as well?</param>
|
||||||
|
@ -105,7 +154,7 @@ namespace GarrysMod.AddonCreator
|
||||||
var fileSize = sr.ReadInt64();
|
var fileSize = sr.ReadInt64();
|
||||||
var fileHash = sr.ReadInt32();
|
var fileHash = sr.ReadInt32();
|
||||||
|
|
||||||
Debug.WriteLine("\t#{2} : {0} ({1:0.0} kB)", filePath, fileSize / 1024, fileId);
|
Debug.WriteLine("\t#{2} : {0} ({1:0.0} kB)", filePath, fileSize/1024, fileId);
|
||||||
Debug.Assert(fileId == expectedFileId);
|
Debug.Assert(fileId == expectedFileId);
|
||||||
|
|
||||||
expectedFileId++;
|
expectedFileId++;
|
||||||
|
@ -113,7 +162,8 @@ namespace GarrysMod.AddonCreator
|
||||||
// avoid duplicates
|
// avoid duplicates
|
||||||
if (newFilesList.ContainsKey(filePath))
|
if (newFilesList.ContainsKey(filePath))
|
||||||
{
|
{
|
||||||
throw new IOException("Found duplicate file path in addon file. Contact the addon creator and tell him to build a new proper addon file.");
|
throw new IOException(
|
||||||
|
"Found duplicate file path in addon file. Contact the addon creator and tell him to build a new proper addon file.");
|
||||||
}
|
}
|
||||||
|
|
||||||
newFilesList.Add(filePath, new Tuple<long, int>(fileSize, fileHash));
|
newFilesList.Add(filePath, new Tuple<long, int>(fileSize, fileHash));
|
||||||
|
@ -127,14 +177,14 @@ namespace GarrysMod.AddonCreator
|
||||||
var fileSize = file.Value.Item1;
|
var fileSize = file.Value.Item1;
|
||||||
var fileHash = file.Value.Item2;
|
var fileHash = file.Value.Item2;
|
||||||
|
|
||||||
Debug.WriteLine("Extracting: {0} ({1:0.00} kB)", filePath, fileSize / 1024);
|
Debug.WriteLine("Extracting: {0} ({1:0.00} kB)", filePath, fileSize/1024);
|
||||||
|
|
||||||
var fileContent = new byte[fileSize];
|
var fileContent = new byte[fileSize];
|
||||||
|
|
||||||
// long-compatible file reading
|
// long-compatible file reading
|
||||||
for (long i = 0; i < fileSize; i += int.MaxValue)
|
for (long i = 0; i < fileSize; i += int.MaxValue)
|
||||||
{
|
{
|
||||||
var tempContent = sr.ReadBytes((int)Math.Min(int.MaxValue, fileSize));
|
var tempContent = sr.ReadBytes((int) Math.Min(int.MaxValue, fileSize));
|
||||||
tempContent.CopyTo(fileContent, i);
|
tempContent.CopyTo(fileContent, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,12 +201,7 @@ namespace GarrysMod.AddonCreator
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the timestamp of when the addon was built. This data is retrieved from full imports and for new (unsaved) addons this is 0.
|
/// Exports this addon into a GMA file.
|
||||||
/// </summary>
|
|
||||||
public ulong BuildTimestamp { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Exports this addon into a GMA file.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">The output file path, should be pointing to a writable location ending with ".gma".</param>
|
/// <param name="path">The output file path, should be pointing to a writable location ending with ".gma".</param>
|
||||||
public void Export(string path)
|
public void Export(string path)
|
||||||
|
@ -178,7 +223,8 @@ namespace GarrysMod.AddonCreator
|
||||||
var files = Files;
|
var files = Files;
|
||||||
|
|
||||||
// Check for errors and ignores in addon.json
|
// Check for errors and ignores in addon.json
|
||||||
var addonJson = JsonConvert.DeserializeObject<AddonJson>(Encoding.UTF8.GetString(Files["addon.json"].GetContents()));
|
var addonJson =
|
||||||
|
JsonConvert.DeserializeObject<AddonJson>(Encoding.UTF8.GetString(Files["addon.json"].GetContents()));
|
||||||
addonJson.CheckForErrors();
|
addonJson.CheckForErrors();
|
||||||
addonJson.RemoveIgnoredFiles(ref files);
|
addonJson.RemoveIgnoredFiles(ref files);
|
||||||
|
|
||||||
|
@ -186,7 +232,7 @@ namespace GarrysMod.AddonCreator
|
||||||
Title = addonJson.Title;
|
Title = addonJson.Title;
|
||||||
Description = string.IsNullOrEmpty(addonJson.Description) ? string.Empty : addonJson.Description;
|
Description = string.IsNullOrEmpty(addonJson.Description) ? string.Empty : addonJson.Description;
|
||||||
Version = addonJson.Version;
|
Version = addonJson.Version;
|
||||||
|
|
||||||
// Create a stripped down version of addon.json for the output gma, it will replace the Description field
|
// Create a stripped down version of addon.json for the output gma, it will replace the Description field
|
||||||
var newDescription = JsonConvert.SerializeObject(new AddonJson
|
var newDescription = JsonConvert.SerializeObject(new AddonJson
|
||||||
{
|
{
|
||||||
|
@ -206,8 +252,8 @@ namespace GarrysMod.AddonCreator
|
||||||
if (blacklistedFiles.Any())
|
if (blacklistedFiles.Any())
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Found files which aren't whitelisted. Remove or ignore those files before you retry packing your addon:"
|
throw new InvalidOperationException("Found files which aren't whitelisted. Remove or ignore those files before you retry packing your addon:"
|
||||||
+ Environment.NewLine + Environment.NewLine
|
+ Environment.NewLine + Environment.NewLine
|
||||||
+ string.Join(Environment.NewLine, blacklistedFiles));
|
+ string.Join(Environment.NewLine, blacklistedFiles));
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var stream = new MemoryStream())
|
using (var stream = new MemoryStream())
|
||||||
|
@ -223,14 +269,15 @@ namespace GarrysMod.AddonCreator
|
||||||
sw.Write(SteamID);
|
sw.Write(SteamID);
|
||||||
|
|
||||||
// Build timestamp
|
// Build timestamp
|
||||||
sw.Write(BuildTimestamp = (ulong)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds);
|
sw.Write(BuildTimestamp = (ulong) (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds);
|
||||||
|
|
||||||
// Required content
|
// Required content
|
||||||
if (RequiredContent.Count > byte.MaxValue)
|
if (RequiredContent.Count > byte.MaxValue)
|
||||||
{
|
{
|
||||||
throw new IndexOutOfRangeException("Required content count must not exceed " + byte.MaxValue + " entries.");
|
throw new IndexOutOfRangeException("Required content count must not exceed " + byte.MaxValue +
|
||||||
|
" entries.");
|
||||||
}
|
}
|
||||||
sw.Write((byte)RequiredContent.Count);
|
sw.Write((byte) RequiredContent.Count);
|
||||||
foreach (var content in RequiredContent)
|
foreach (var content in RequiredContent)
|
||||||
{
|
{
|
||||||
sw.Write(content, true);
|
sw.Write(content, true);
|
||||||
|
@ -245,7 +292,8 @@ namespace GarrysMod.AddonCreator
|
||||||
// File list
|
// File list
|
||||||
if (Files.Count > uint.MaxValue)
|
if (Files.Count > uint.MaxValue)
|
||||||
{
|
{
|
||||||
throw new IndexOutOfRangeException("Number of addon files must not exceed " + uint.MaxValue + " elements.");
|
throw new IndexOutOfRangeException("Number of addon files must not exceed " + uint.MaxValue +
|
||||||
|
" elements.");
|
||||||
}
|
}
|
||||||
uint fileNum = 0;
|
uint fileNum = 0;
|
||||||
foreach (var file in resultingFiles)
|
foreach (var file in resultingFiles)
|
||||||
|
@ -256,7 +304,7 @@ namespace GarrysMod.AddonCreator
|
||||||
sw.Write(file.Value.Size);
|
sw.Write(file.Value.Size);
|
||||||
sw.Write(file.Value.Crc32Hash);
|
sw.Write(file.Value.Crc32Hash);
|
||||||
}
|
}
|
||||||
sw.Write((uint)0); // End of file list
|
sw.Write((uint) 0); // End of file list
|
||||||
|
|
||||||
// File contents
|
// File contents
|
||||||
foreach (var file in resultingFiles)
|
foreach (var file in resultingFiles)
|
||||||
|
@ -278,50 +326,5 @@ namespace GarrysMod.AddonCreator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The name of this addon.
|
|
||||||
/// </summary>
|
|
||||||
public string Title { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The author of this addon.
|
|
||||||
/// </summary>
|
|
||||||
public string Author { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A description of this addon.
|
|
||||||
/// </summary>
|
|
||||||
public string Description { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This addon's version.
|
|
||||||
/// </summary>
|
|
||||||
public int Version { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The files to include in the addon.
|
|
||||||
/// </summary>
|
|
||||||
public Dictionary<string, AddonFileInfo> Files { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Currently unused.
|
|
||||||
/// </summary>
|
|
||||||
public ulong SteamID { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Content that needs to exist in order to run this addon.
|
|
||||||
/// </summary>
|
|
||||||
public List<string> RequiredContent { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of <see cref="Addon"/>
|
|
||||||
/// </summary>
|
|
||||||
public Addon()
|
|
||||||
{
|
|
||||||
Files = new Dictionary<string, AddonFileInfo>();
|
|
||||||
RequiredContent = new List<string>();
|
|
||||||
Version = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,12 +4,18 @@ namespace GarrysMod.AddonCreator
|
||||||
{
|
{
|
||||||
public abstract class AddonFileInfo
|
public abstract class AddonFileInfo
|
||||||
{
|
{
|
||||||
private long? _size;
|
|
||||||
private int? _hash;
|
private int? _hash;
|
||||||
|
private long? _size;
|
||||||
|
|
||||||
public virtual long Size { get { return _size.HasValue ? _size.Value : (_size = GetContents().Length).Value; } }
|
public virtual long Size
|
||||||
|
{
|
||||||
|
get { return _size.HasValue ? _size.Value : (_size = GetContents().Length).Value; }
|
||||||
|
}
|
||||||
|
|
||||||
public virtual int Crc32Hash { get { return _hash.HasValue ? _hash.Value : (_hash = ParallelCRC.Compute(GetContents())).Value; } }
|
public virtual int Crc32Hash
|
||||||
|
{
|
||||||
|
get { return _hash.HasValue ? _hash.Value : (_hash = ParallelCRC.Compute(GetContents())).Value; }
|
||||||
|
}
|
||||||
|
|
||||||
public abstract byte[] GetContents();
|
public abstract byte[] GetContents();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace GarrysMod.AddonCreator
|
namespace GarrysMod.AddonCreator
|
||||||
|
@ -14,7 +13,7 @@ namespace GarrysMod.AddonCreator
|
||||||
Version = 1;
|
Version = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonProperty("title", NullValueHandling=NullValueHandling.Ignore)]
|
[JsonProperty("title", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
|
||||||
[JsonProperty("description")]
|
[JsonProperty("description")]
|
||||||
|
@ -60,4 +59,4 @@ namespace GarrysMod.AddonCreator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,8 +1,5 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace GarrysMod.AddonCreator
|
namespace GarrysMod.AddonCreator
|
||||||
|
@ -10,69 +7,69 @@ namespace GarrysMod.AddonCreator
|
||||||
public static class AddonWhitelist
|
public static class AddonWhitelist
|
||||||
{
|
{
|
||||||
private static readonly string[] Whitelist =
|
private static readonly string[] Whitelist =
|
||||||
{
|
{
|
||||||
"addon.json",
|
"addon.json",
|
||||||
"lua/*.lua",
|
"lua/*.lua",
|
||||||
"scenes/*.vcd",
|
"scenes/*.vcd",
|
||||||
"particles/*.pcf",
|
"particles/*.pcf",
|
||||||
"resource/fonts/*.ttf",
|
"resource/fonts/*.ttf",
|
||||||
"scripts/vehicles/*.txt",
|
"scripts/vehicles/*.txt",
|
||||||
"resource/localization/*/*.properties",
|
"resource/localization/*/*.properties",
|
||||||
"maps/*.bsp",
|
"maps/*.bsp",
|
||||||
"maps/*.nav",
|
"maps/*.nav",
|
||||||
"maps/*.ain",
|
"maps/*.ain",
|
||||||
"maps/thumb/*.png",
|
"maps/thumb/*.png",
|
||||||
"sound/*.wav",
|
"sound/*.wav",
|
||||||
"sound/*.mp3",
|
"sound/*.mp3",
|
||||||
"sound/*.ogg",
|
"sound/*.ogg",
|
||||||
"materials/*.vmt",
|
"materials/*.vmt",
|
||||||
"materials/*.vtf",
|
"materials/*.vtf",
|
||||||
"materials/*.png",
|
"materials/*.png",
|
||||||
"materials/*.jpg",
|
"materials/*.jpg",
|
||||||
"materials/*.jpeg",
|
"materials/*.jpeg",
|
||||||
"models/*.mdl",
|
"models/*.mdl",
|
||||||
"models/*.vtx",
|
"models/*.vtx",
|
||||||
"models/*.phy",
|
"models/*.phy",
|
||||||
"models/*.ani",
|
"models/*.ani",
|
||||||
"models/*.vvd",
|
"models/*.vvd",
|
||||||
"gamemodes/*/*.txt",
|
"gamemodes/*/*.txt",
|
||||||
"gamemodes/*/*.fgd",
|
"gamemodes/*/*.fgd",
|
||||||
"gamemodes/*/logo.png",
|
"gamemodes/*/logo.png",
|
||||||
"gamemodes/*/icon24.png",
|
"gamemodes/*/icon24.png",
|
||||||
"gamemodes/*/gamemode/*.lua",
|
"gamemodes/*/gamemode/*.lua",
|
||||||
"gamemodes/*/entities/effects/*.lua",
|
"gamemodes/*/entities/effects/*.lua",
|
||||||
"gamemodes/*/entities/weapons/*.lua",
|
"gamemodes/*/entities/weapons/*.lua",
|
||||||
"gamemodes/*/entities/entities/*.lua",
|
"gamemodes/*/entities/entities/*.lua",
|
||||||
"gamemodes/*/backgrounds/*.png",
|
"gamemodes/*/backgrounds/*.png",
|
||||||
"gamemodes/*/backgrounds/*.jpg",
|
"gamemodes/*/backgrounds/*.jpg",
|
||||||
"gamemodes/*/backgrounds/*.jpeg",
|
"gamemodes/*/backgrounds/*.jpeg",
|
||||||
"gamemodes/*/content/models/*.mdl",
|
"gamemodes/*/content/models/*.mdl",
|
||||||
"gamemodes/*/content/models/*.vtx",
|
"gamemodes/*/content/models/*.vtx",
|
||||||
"gamemodes/*/content/models/*.phy",
|
"gamemodes/*/content/models/*.phy",
|
||||||
"gamemodes/*/content/models/*.ani",
|
"gamemodes/*/content/models/*.ani",
|
||||||
"gamemodes/*/content/models/*.vvd",
|
"gamemodes/*/content/models/*.vvd",
|
||||||
"gamemodes/*/content/materials/*.vmt",
|
"gamemodes/*/content/materials/*.vmt",
|
||||||
"gamemodes/*/content/materials/*.vtf",
|
"gamemodes/*/content/materials/*.vtf",
|
||||||
"gamemodes/*/content/materials/*.png",
|
"gamemodes/*/content/materials/*.png",
|
||||||
"gamemodes/*/content/materials/*.jpg",
|
"gamemodes/*/content/materials/*.jpg",
|
||||||
"gamemodes/*/content/materials/*.jpeg",
|
"gamemodes/*/content/materials/*.jpeg",
|
||||||
"gamemodes/*/content/scenes/*.vcd",
|
"gamemodes/*/content/scenes/*.vcd",
|
||||||
"gamemodes/*/content/particles/*.pcf",
|
"gamemodes/*/content/particles/*.pcf",
|
||||||
"gamemodes/*/content/resource/fonts/*.ttf",
|
"gamemodes/*/content/resource/fonts/*.ttf",
|
||||||
"gamemodes/*/content/scripts/vehicles/*.txt",
|
"gamemodes/*/content/scripts/vehicles/*.txt",
|
||||||
"gamemodes/*/content/resource/localization/*/*.properties",
|
"gamemodes/*/content/resource/localization/*/*.properties",
|
||||||
"gamemodes/*/content/maps/*.bsp",
|
"gamemodes/*/content/maps/*.bsp",
|
||||||
"gamemodes/*/content/maps/*.nav",
|
"gamemodes/*/content/maps/*.nav",
|
||||||
"gamemodes/*/content/maps/*.ain",
|
"gamemodes/*/content/maps/*.ain",
|
||||||
"gamemodes/*/content/maps/thumb/*.png",
|
"gamemodes/*/content/maps/thumb/*.png",
|
||||||
"gamemodes/*/content/sound/*.wav",
|
"gamemodes/*/content/sound/*.wav",
|
||||||
"gamemodes/*/content/sound/*.mp3",
|
"gamemodes/*/content/sound/*.mp3",
|
||||||
"gamemodes/*/content/sound/*.ogg"
|
"gamemodes/*/content/sound/*.ogg"
|
||||||
};
|
};
|
||||||
|
|
||||||
private static Regex[] _regularExpressions;
|
private static Regex[] _regularExpressions;
|
||||||
|
|
||||||
static void ConvertWhitelist()
|
private static void ConvertWhitelist()
|
||||||
{
|
{
|
||||||
if (_regularExpressions != null)
|
if (_regularExpressions != null)
|
||||||
return;
|
return;
|
||||||
|
@ -86,4 +83,4 @@ namespace GarrysMod.AddonCreator
|
||||||
return files.Where(f => !_regularExpressions.Any(rx => rx.IsMatch(f)));
|
return files.Where(f => !_regularExpressions.Any(rx => rx.IsMatch(f)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,13 +1,10 @@
|
||||||
using System;
|
using System.IO;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace GarrysMod.AddonCreator
|
namespace GarrysMod.AddonCreator
|
||||||
{
|
{
|
||||||
static class Extensions
|
internal static class Extensions
|
||||||
{
|
{
|
||||||
public static Regex WildcardRegex(this string pattern)
|
public static Regex WildcardRegex(this string pattern)
|
||||||
{
|
{
|
||||||
|
@ -43,4 +40,4 @@ namespace GarrysMod.AddonCreator
|
||||||
bw.Write(value);
|
bw.Write(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace CRC32
|
namespace CRC32
|
||||||
{
|
{
|
||||||
|
@ -7,14 +6,16 @@ namespace CRC32
|
||||||
{
|
{
|
||||||
private const uint kCrcPoly = 0xEDB88320;
|
private const uint kCrcPoly = 0xEDB88320;
|
||||||
private const uint kInitial = 0xFFFFFFFF;
|
private const uint kInitial = 0xFFFFFFFF;
|
||||||
private static readonly uint[] Table;
|
|
||||||
private const uint CRC_NUM_TABLES = 8;
|
private const uint CRC_NUM_TABLES = 8;
|
||||||
|
private static readonly uint[] Table;
|
||||||
|
|
||||||
|
private uint value;
|
||||||
|
|
||||||
static OptimizedCRC()
|
static OptimizedCRC()
|
||||||
{
|
{
|
||||||
unchecked
|
unchecked
|
||||||
{
|
{
|
||||||
Table = new uint[256 * CRC_NUM_TABLES];
|
Table = new uint[256*CRC_NUM_TABLES];
|
||||||
uint i;
|
uint i;
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
{
|
{
|
||||||
|
@ -23,7 +24,7 @@ namespace CRC32
|
||||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||||
Table[i] = r;
|
Table[i] = r;
|
||||||
}
|
}
|
||||||
for (; i < 256 * CRC_NUM_TABLES; i++)
|
for (; i < 256*CRC_NUM_TABLES; i++)
|
||||||
{
|
{
|
||||||
uint r = Table[i - 256];
|
uint r = Table[i - 256];
|
||||||
Table[i] = Table[r & 0xFF] ^ (r >> 8);
|
Table[i] = Table[r & 0xFF] ^ (r >> 8);
|
||||||
|
@ -31,42 +32,40 @@ namespace CRC32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint value;
|
|
||||||
|
|
||||||
public OptimizedCRC()
|
public OptimizedCRC()
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int Value
|
||||||
|
{
|
||||||
|
get { return (int) ~value; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reset CRC
|
/// Reset CRC
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
value = kInitial;
|
value = kInitial;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Value
|
|
||||||
{
|
|
||||||
get { return (int)~value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateByte(byte b)
|
public void UpdateByte(byte b)
|
||||||
{
|
{
|
||||||
value = (value >> 8) ^ Table[(byte)value ^ b];
|
value = (value >> 8) ^ Table[(byte) value ^ b];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(byte[] data, int offset, int count)
|
public void Update(byte[] data, int offset, int count)
|
||||||
{
|
{
|
||||||
new ArraySegment<byte>(data, offset, count); // check arguments
|
new ArraySegment<byte>(data, offset, count); // check arguments
|
||||||
if (count == 0) return;
|
if (count == 0) return;
|
||||||
|
|
||||||
var table = OptimizedCRC.Table; // important for performance!
|
var table = Table; // important for performance!
|
||||||
|
|
||||||
uint crc = value;
|
uint crc = value;
|
||||||
|
|
||||||
for (; (offset & 7) != 0 && count != 0; count--)
|
for (; (offset & 7) != 0 && count != 0; count--)
|
||||||
crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]];
|
crc = (crc >> 8) ^ table[(byte) crc ^ data[offset++]];
|
||||||
|
|
||||||
if (count >= 8)
|
if (count >= 8)
|
||||||
{
|
{
|
||||||
|
@ -80,40 +79,46 @@ namespace CRC32
|
||||||
|
|
||||||
while (offset != to)
|
while (offset != to)
|
||||||
{
|
{
|
||||||
crc ^= (uint)(data[offset] + (data[offset + 1] << 8) + (data[offset + 2] << 16) + (data[offset + 3] << 24));
|
crc ^=
|
||||||
uint high = (uint)(data[offset + 4] + (data[offset + 5] << 8) + (data[offset + 6] << 16) + (data[offset + 7] << 24));
|
(uint)
|
||||||
|
(data[offset] + (data[offset + 1] << 8) + (data[offset + 2] << 16) +
|
||||||
|
(data[offset + 3] << 24));
|
||||||
|
var high =
|
||||||
|
(uint)
|
||||||
|
(data[offset + 4] + (data[offset + 5] << 8) + (data[offset + 6] << 16) +
|
||||||
|
(data[offset + 7] << 24));
|
||||||
offset += 8;
|
offset += 8;
|
||||||
|
|
||||||
crc = table[(byte)crc + 0x700]
|
crc = table[(byte) crc + 0x700]
|
||||||
^ table[(byte)(crc >>= 8) + 0x600]
|
^ table[(byte) (crc >>= 8) + 0x600]
|
||||||
^ table[(byte)(crc >>= 8) + 0x500]
|
^ table[(byte) (crc >>= 8) + 0x500]
|
||||||
^ table[/*(byte)*/(crc >> 8) + 0x400]
|
^ table[ /*(byte)*/(crc >> 8) + 0x400]
|
||||||
^ table[(byte)(high) + 0x300]
|
^ table[(byte) (high) + 0x300]
|
||||||
^ table[(byte)(high >>= 8) + 0x200]
|
^ table[(byte) (high >>= 8) + 0x200]
|
||||||
^ table[(byte)(high >>= 8) + 0x100]
|
^ table[(byte) (high >>= 8) + 0x100]
|
||||||
^ table[/*(byte)*/(high >> 8) + 0x000];
|
^ table[ /*(byte)*/(high >> 8) + 0x000];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (count-- != 0)
|
while (count-- != 0)
|
||||||
crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]];
|
crc = (crc >> 8) ^ table[(byte) crc ^ data[offset++]];
|
||||||
|
|
||||||
value = crc;
|
value = crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static public int Compute(byte[] data, int offset, int size)
|
public static int Compute(byte[] data, int offset, int size)
|
||||||
{
|
{
|
||||||
var crc = new OptimizedCRC();
|
var crc = new OptimizedCRC();
|
||||||
crc.Update(data, offset, size);
|
crc.Update(data, offset, size);
|
||||||
return crc.Value;
|
return crc.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static public int Compute(byte[] data)
|
public static int Compute(byte[] data)
|
||||||
{
|
{
|
||||||
return Compute(data, 0, data.Length);
|
return Compute(data, 0, data.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static public int Compute(ArraySegment<byte> block)
|
public static int Compute(ArraySegment<byte> block)
|
||||||
{
|
{
|
||||||
return Compute(block.Array, block.Offset, block.Count);
|
return Compute(block.Array, block.Offset, block.Count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace CRC32
|
namespace CRC32
|
||||||
{
|
{
|
||||||
|
@ -9,27 +7,29 @@ namespace CRC32
|
||||||
{
|
{
|
||||||
private const uint kCrcPoly = 0xEDB88320;
|
private const uint kCrcPoly = 0xEDB88320;
|
||||||
private const uint kInitial = 0xFFFFFFFF;
|
private const uint kInitial = 0xFFFFFFFF;
|
||||||
private static readonly uint[] Table;
|
|
||||||
private const int CRC_NUM_TABLES = 8;
|
private const int CRC_NUM_TABLES = 8;
|
||||||
|
|
||||||
private const int ThreadCost = 256 << 10;
|
private const int ThreadCost = 256 << 10;
|
||||||
private static int ThreadCount = Environment.ProcessorCount;
|
private static readonly uint[] Table;
|
||||||
|
private static readonly int ThreadCount = Environment.ProcessorCount;
|
||||||
|
|
||||||
|
|
||||||
|
private uint value;
|
||||||
|
|
||||||
static ParallelCRC()
|
static ParallelCRC()
|
||||||
{
|
{
|
||||||
unchecked
|
unchecked
|
||||||
{
|
{
|
||||||
Table = new uint[256 * CRC_NUM_TABLES];
|
Table = new uint[256*CRC_NUM_TABLES];
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
{
|
{
|
||||||
uint r = (uint)i;
|
var r = (uint) i;
|
||||||
for (int j = 0; j < 8; j++)
|
for (int j = 0; j < 8; j++)
|
||||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||||
Table[i] = r;
|
Table[i] = r;
|
||||||
}
|
}
|
||||||
for (; i < 256 * CRC_NUM_TABLES; i++)
|
for (; i < 256*CRC_NUM_TABLES; i++)
|
||||||
{
|
{
|
||||||
uint r = Table[i - 256];
|
uint r = Table[i - 256];
|
||||||
Table[i] = Table[r & 0xFF] ^ (r >> 8);
|
Table[i] = Table[r & 0xFF] ^ (r >> 8);
|
||||||
|
@ -37,34 +37,32 @@ namespace CRC32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint value;
|
|
||||||
|
|
||||||
public ParallelCRC()
|
public ParallelCRC()
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int Value
|
||||||
|
{
|
||||||
|
get { return (int) ~value; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reset CRC
|
/// Reset CRC
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
value = kInitial;
|
value = kInitial;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Value
|
|
||||||
{
|
|
||||||
get { return (int)~value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateByte(byte b)
|
public void UpdateByte(byte b)
|
||||||
{
|
{
|
||||||
value = (value >> 8) ^ Table[(byte)value ^ b];
|
value = (value >> 8) ^ Table[(byte) value ^ b];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(byte[] data, int offset, int count)
|
public void Update(byte[] data, int offset, int count)
|
||||||
{
|
{
|
||||||
new ArraySegment<byte>(data, offset, count); // check arguments
|
new ArraySegment<byte>(data, offset, count); // check arguments
|
||||||
|
|
||||||
if (count <= ThreadCost || ThreadCount <= 1)
|
if (count <= ThreadCost || ThreadCount <= 1)
|
||||||
{
|
{
|
||||||
|
@ -75,8 +73,8 @@ namespace CRC32
|
||||||
// choose optimal number of threads to use
|
// choose optimal number of threads to use
|
||||||
|
|
||||||
int threadCount = ThreadCount;
|
int threadCount = ThreadCount;
|
||||||
L0:
|
L0:
|
||||||
int bytesPerThread = (count + threadCount - 1) / threadCount;
|
int bytesPerThread = (count + threadCount - 1)/threadCount;
|
||||||
if (bytesPerThread < ThreadCost >> 1)
|
if (bytesPerThread < ThreadCost >> 1)
|
||||||
{
|
{
|
||||||
threadCount--;
|
threadCount--;
|
||||||
|
@ -110,10 +108,10 @@ namespace CRC32
|
||||||
if (count < 0) throw new ArgumentOutOfRangeException("count");
|
if (count < 0) throw new ArgumentOutOfRangeException("count");
|
||||||
if (count == 0) return crc;
|
if (count == 0) return crc;
|
||||||
|
|
||||||
var table = ParallelCRC.Table;
|
var table = Table;
|
||||||
|
|
||||||
for (; (offset & 7) != 0 && count != 0; count--)
|
for (; (offset & 7) != 0 && count != 0; count--)
|
||||||
crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]];
|
crc = (crc >> 8) ^ table[(byte) crc ^ data[offset++]];
|
||||||
|
|
||||||
if (count >= 8)
|
if (count >= 8)
|
||||||
{
|
{
|
||||||
|
@ -123,40 +121,46 @@ namespace CRC32
|
||||||
|
|
||||||
while (offset != to)
|
while (offset != to)
|
||||||
{
|
{
|
||||||
crc ^= (uint)(data[offset] + (data[offset + 1] << 8) + (data[offset + 2] << 16) + (data[offset + 3] << 24));
|
crc ^=
|
||||||
uint high = (uint)(data[offset + 4] + (data[offset + 5] << 8) + (data[offset + 6] << 16) + (data[offset + 7] << 24));
|
(uint)
|
||||||
|
(data[offset] + (data[offset + 1] << 8) + (data[offset + 2] << 16) +
|
||||||
|
(data[offset + 3] << 24));
|
||||||
|
var high =
|
||||||
|
(uint)
|
||||||
|
(data[offset + 4] + (data[offset + 5] << 8) + (data[offset + 6] << 16) +
|
||||||
|
(data[offset + 7] << 24));
|
||||||
offset += 8;
|
offset += 8;
|
||||||
|
|
||||||
crc = table[(byte)crc + 0x700]
|
crc = table[(byte) crc + 0x700]
|
||||||
^ table[(byte)(crc >>= 8) + 0x600]
|
^ table[(byte) (crc >>= 8) + 0x600]
|
||||||
^ table[(byte)(crc >>= 8) + 0x500]
|
^ table[(byte) (crc >>= 8) + 0x500]
|
||||||
^ table[/*(byte)*/(crc >> 8) + 0x400]
|
^ table[ /*(byte)*/(crc >> 8) + 0x400]
|
||||||
^ table[(byte)(high) + 0x300]
|
^ table[(byte) (high) + 0x300]
|
||||||
^ table[(byte)(high >>= 8) + 0x200]
|
^ table[(byte) (high >>= 8) + 0x200]
|
||||||
^ table[(byte)(high >>= 8) + 0x100]
|
^ table[(byte) (high >>= 8) + 0x100]
|
||||||
^ table[/*(byte)*/(high >> 8) + 0x000];
|
^ table[ /*(byte)*/(high >> 8) + 0x000];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (count-- != 0)
|
while (count-- != 0)
|
||||||
crc = (crc >> 8) ^ table[(byte)crc ^ data[offset++]];
|
crc = (crc >> 8) ^ table[(byte) crc ^ data[offset++]];
|
||||||
|
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static public int Compute(byte[] data, int offset, int count)
|
public static int Compute(byte[] data, int offset, int count)
|
||||||
{
|
{
|
||||||
var crc = new ParallelCRC();
|
var crc = new ParallelCRC();
|
||||||
crc.Update(data, offset, count);
|
crc.Update(data, offset, count);
|
||||||
return crc.Value;
|
return crc.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static public int Compute(byte[] data)
|
public static int Compute(byte[] data)
|
||||||
{
|
{
|
||||||
return Compute(data, 0, data.Length);
|
return Compute(data, 0, data.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static public int Compute(ArraySegment<byte> block)
|
public static int Compute(ArraySegment<byte> block)
|
||||||
{
|
{
|
||||||
return Compute(block.Array, block.Offset, block.Count);
|
return Compute(block.Array, block.Offset, block.Count);
|
||||||
}
|
}
|
||||||
|
@ -168,8 +172,11 @@ namespace CRC32
|
||||||
* Taken from DotNetZip project sources (http://dotnetzip.codeplex.com/)
|
* Taken from DotNetZip project sources (http://dotnetzip.codeplex.com/)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
private static uint[] even_cache;
|
||||||
|
private static uint[] odd_cache;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This function is thread-safe!
|
/// This function is thread-safe!
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static uint Combine(uint crc1, uint crc2, int length2)
|
private static uint Combine(uint crc1, uint crc2, int length2)
|
||||||
{
|
{
|
||||||
|
@ -187,7 +194,7 @@ namespace CRC32
|
||||||
crc1 = ~crc1;
|
crc1 = ~crc1;
|
||||||
crc2 = ~crc2;
|
crc2 = ~crc2;
|
||||||
|
|
||||||
uint len2 = (uint)length2;
|
var len2 = (uint) length2;
|
||||||
|
|
||||||
// apply len2 zeros to crc1 (first square will put the operator for one
|
// apply len2 zeros to crc1 (first square will put the operator for one
|
||||||
// zero byte, eight zero bits, in even)
|
// zero byte, eight zero bits, in even)
|
||||||
|
@ -211,16 +218,13 @@ namespace CRC32
|
||||||
return ~crc1;
|
return ~crc1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static uint[] even_cache = null;
|
|
||||||
private static uint[] odd_cache;
|
|
||||||
|
|
||||||
private static void Prepare_even_odd_Cache()
|
private static void Prepare_even_odd_Cache()
|
||||||
{
|
{
|
||||||
var even = new uint[32]; // even-power-of-two zeros operator
|
var even = new uint[32]; // even-power-of-two zeros operator
|
||||||
var odd = new uint[32]; // odd-power-of-two zeros operator
|
var odd = new uint[32]; // odd-power-of-two zeros operator
|
||||||
|
|
||||||
// put operator for one zero bit in odd
|
// put operator for one zero bit in odd
|
||||||
odd[0] = kCrcPoly; // the CRC-32 polynomial
|
odd[0] = kCrcPoly; // the CRC-32 polynomial
|
||||||
for (int i = 1; i < 32; i++) odd[i] = 1U << (i - 1);
|
for (int i = 1; i < 32; i++) odd[i] = 1U << (i - 1);
|
||||||
|
|
||||||
// put operator for two zero bits in even
|
// put operator for two zero bits in even
|
||||||
|
@ -258,17 +262,17 @@ namespace CRC32
|
||||||
private static uint[] CopyArray(uint[] a)
|
private static uint[] CopyArray(uint[] a)
|
||||||
{
|
{
|
||||||
var b = new uint[a.Length];
|
var b = new uint[a.Length];
|
||||||
Buffer.BlockCopy(a, 0, b, 0, a.Length * sizeof(uint));
|
Buffer.BlockCopy(a, 0, b, 0, a.Length*sizeof (uint));
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Combining
|
#endregion Combining
|
||||||
|
|
||||||
class Job
|
private class Job
|
||||||
{
|
{
|
||||||
|
private readonly ParallelCRC accumulator;
|
||||||
|
private readonly Job waitForJob;
|
||||||
private ArraySegment<byte> data;
|
private ArraySegment<byte> data;
|
||||||
private Job waitForJob;
|
|
||||||
private ParallelCRC accumulator;
|
|
||||||
|
|
||||||
private ManualResetEventSlim finished;
|
private ManualResetEventSlim finished;
|
||||||
|
|
||||||
|
@ -277,7 +281,7 @@ namespace CRC32
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.accumulator = accumulator;
|
this.accumulator = accumulator;
|
||||||
this.waitForJob = waitForJob;
|
this.waitForJob = waitForJob;
|
||||||
this.finished = new ManualResetEventSlim(false);
|
finished = new ManualResetEventSlim(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Do(object arg)
|
public void Do(object arg)
|
||||||
|
@ -301,5 +305,4 @@ namespace CRC32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -4,13 +4,13 @@ namespace GarrysMod.AddonCreator
|
||||||
{
|
{
|
||||||
public class PhysicalAddonFileInfo : AddonFileInfo
|
public class PhysicalAddonFileInfo : AddonFileInfo
|
||||||
{
|
{
|
||||||
|
private readonly FileInfo _fi;
|
||||||
|
|
||||||
public PhysicalAddonFileInfo(string path)
|
public PhysicalAddonFileInfo(string path)
|
||||||
{
|
{
|
||||||
_fi = new FileInfo(path);
|
_fi = new FileInfo(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileInfo _fi;
|
|
||||||
|
|
||||||
public override long Size
|
public override long Size
|
||||||
{
|
{
|
||||||
get { return _fi.Length; }
|
get { return _fi.Length; }
|
||||||
|
|
|
@ -19,7 +19,8 @@ namespace GarrysMod.AddonCreator
|
||||||
// recursively add files
|
// recursively add files
|
||||||
foreach (var file in folder.EnumerateFiles("*", SearchOption.AllDirectories))
|
foreach (var file in folder.EnumerateFiles("*", SearchOption.AllDirectories))
|
||||||
{
|
{
|
||||||
var relpath = MakeRelativePath(folder.FullName, file.FullName).Replace(Path.DirectorySeparatorChar, '/');
|
var relpath =
|
||||||
|
MakeRelativePath(folder.FullName, file.FullName).Replace(Path.DirectorySeparatorChar, '/');
|
||||||
Console.WriteLine("Adding: {0}", relpath);
|
Console.WriteLine("Adding: {0}", relpath);
|
||||||
|
|
||||||
addon.Files.Add(relpath, new PhysicalAddonFileInfo(file.FullName));
|
addon.Files.Add(relpath, new PhysicalAddonFileInfo(file.FullName));
|
||||||
|
@ -45,7 +46,8 @@ namespace GarrysMod.AddonCreator
|
||||||
foreach (var file in addon.Files)
|
foreach (var file in addon.Files)
|
||||||
{
|
{
|
||||||
var relpath = file.Key;
|
var relpath = file.Key;
|
||||||
var targetFile = new FileInfo(Path.Combine(folder.FullName, relpath.Replace('/', Path.DirectorySeparatorChar)));
|
var targetFile =
|
||||||
|
new FileInfo(Path.Combine(folder.FullName, relpath.Replace('/', Path.DirectorySeparatorChar)));
|
||||||
|
|
||||||
Console.WriteLine("Extracting: {0}", relpath);
|
Console.WriteLine("Extracting: {0}", relpath);
|
||||||
|
|
||||||
|
@ -63,7 +65,7 @@ namespace GarrysMod.AddonCreator
|
||||||
// long-compatible copy algorithm
|
// long-compatible copy algorithm
|
||||||
for (long i = 0; i < buffer.LongLength; i += int.MaxValue)
|
for (long i = 0; i < buffer.LongLength; i += int.MaxValue)
|
||||||
{
|
{
|
||||||
var toWrite = (int)Math.Min(int.MaxValue, buffer.LongLength - i);
|
var toWrite = (int) Math.Min(int.MaxValue, buffer.LongLength - i);
|
||||||
var toWriteBuf = buffer.AsEnumerable();
|
var toWriteBuf = buffer.AsEnumerable();
|
||||||
for (long j = 0; j < i; j += int.MaxValue)
|
for (long j = 0; j < i; j += int.MaxValue)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
||||||
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
|
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
|
||||||
// die mit einer Assembly verknüpft sind.
|
// die mit einer Assembly verknüpft sind.
|
||||||
|
|
||||||
[assembly: AssemblyTitle("GarrysMod.AddonCreator")]
|
[assembly: AssemblyTitle("GarrysMod.AddonCreator")]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription("")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
@ -17,9 +17,11 @@ using System.Runtime.InteropServices;
|
||||||
// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
|
// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
|
||||||
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
|
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
|
||||||
// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
|
// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
|
||||||
|
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
|
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
|
||||||
|
|
||||||
[assembly: Guid("bb585862-950d-415b-b518-eb9c7e3d50f3")]
|
[assembly: Guid("bb585862-950d-415b-b518-eb9c7e3d50f3")]
|
||||||
|
|
||||||
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
|
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
|
||||||
|
@ -32,5 +34,6 @@ using System.Runtime.InteropServices;
|
||||||
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
|
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
|
||||||
// übernehmen, indem Sie "*" eingeben:
|
// übernehmen, indem Sie "*" eingeben:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -5,9 +5,9 @@ namespace GarrysMod.AddonCreator
|
||||||
{
|
{
|
||||||
public class SegmentedAddonFileInfo : AddonFileInfo
|
public class SegmentedAddonFileInfo : AddonFileInfo
|
||||||
{
|
{
|
||||||
private Stream _stream;
|
private readonly long _len;
|
||||||
private long _pos;
|
private readonly long _pos;
|
||||||
private long _len;
|
private readonly Stream _stream;
|
||||||
private int _hash;
|
private int _hash;
|
||||||
|
|
||||||
public SegmentedAddonFileInfo(Stream stream, long pos, long len, int fileHash)
|
public SegmentedAddonFileInfo(Stream stream, long pos, long len, int fileHash)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace CRC32
|
namespace CRC32
|
||||||
{
|
{
|
||||||
|
@ -9,6 +8,8 @@ namespace CRC32
|
||||||
private const uint kInitial = 0xFFFFFFFF;
|
private const uint kInitial = 0xFFFFFFFF;
|
||||||
private static readonly uint[] Table;
|
private static readonly uint[] Table;
|
||||||
|
|
||||||
|
private uint value;
|
||||||
|
|
||||||
static TraditionalCRC()
|
static TraditionalCRC()
|
||||||
{
|
{
|
||||||
unchecked
|
unchecked
|
||||||
|
@ -24,51 +25,49 @@ namespace CRC32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint value;
|
|
||||||
|
|
||||||
public TraditionalCRC()
|
public TraditionalCRC()
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int Value
|
||||||
|
{
|
||||||
|
get { return (int) ~value; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reset CRC
|
/// Reset CRC
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
value = kInitial;
|
value = kInitial;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Value
|
|
||||||
{
|
|
||||||
get { return (int)~value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateByte(byte b)
|
public void UpdateByte(byte b)
|
||||||
{
|
{
|
||||||
value = (value >> 8) ^ Table[(byte)value ^ b];
|
value = (value >> 8) ^ Table[(byte) value ^ b];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(byte[] data, int offset, int count)
|
public void Update(byte[] data, int offset, int count)
|
||||||
{
|
{
|
||||||
if (count < 0) throw new ArgumentOutOfRangeException("count");
|
if (count < 0) throw new ArgumentOutOfRangeException("count");
|
||||||
while (count-- != 0)
|
while (count-- != 0)
|
||||||
value = (value >> 8) ^ Table[(byte)value ^ data[offset++]];
|
value = (value >> 8) ^ Table[(byte) value ^ data[offset++]];
|
||||||
}
|
}
|
||||||
|
|
||||||
static public int Compute(byte[] data, int offset, int count)
|
public static int Compute(byte[] data, int offset, int count)
|
||||||
{
|
{
|
||||||
var crc = new TraditionalCRC();
|
var crc = new TraditionalCRC();
|
||||||
crc.Update(data, offset, count);
|
crc.Update(data, offset, count);
|
||||||
return crc.Value;
|
return crc.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static public int Compute(byte[] data)
|
public static int Compute(byte[] data)
|
||||||
{
|
{
|
||||||
return Compute(data, 0, data.Length);
|
return Compute(data, 0, data.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static public int Compute(ArraySegment<byte> block)
|
public static int Compute(ArraySegment<byte> block)
|
||||||
{
|
{
|
||||||
return Compute(block.Array, block.Offset, block.Count);
|
return Compute(block.Array, block.Offset, block.Count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Newtonsoft.Json" version="6.0.5" targetFramework="net40" />
|
<package id="Newtonsoft.Json" version="6.0.5" targetFramework="net40" />
|
||||||
</packages>
|
</packages>
|
Loading…
Reference in New Issue