zxl
/
CTT
forked from Cal/CTT
1
0
Fork 0
CTT/Unity/Assets/Model/XAssetRuntime/Core/Versions.cs

207 lines
6.1 KiB
C#
Raw Normal View History

2021-04-08 20:09:59 +08:00
//
// Versions.cs
//
// Author:
// fjy <jiyuan.feng@live.com>
//
// Copyright (c) 2020 fjy
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace libx
{
public enum VerifyBy
{
Size,
Hash,
}
public static class Versions
{
public const string Dataname = "res";
public const string Filename = "ver";
public static readonly VerifyBy verifyBy = VerifyBy.Hash;
private static readonly VDisk _disk = new VDisk ();
private static readonly Dictionary<string, VFile> _updateData = new Dictionary<string, VFile> ();
private static readonly Dictionary<string, VFile> _baseData = new Dictionary<string, VFile> ();
public static AssetBundle LoadAssetBundleFromFile (string url)
{
if (!File.Exists (url)) {
if (_disk != null) {
var name = Path.GetFileName (url);
var file = _disk.GetFile (name, string.Empty);
if (file != null) {
return AssetBundle.LoadFromFile (_disk.name, 0, (ulong)file.offset);
}
}
}
return AssetBundle.LoadFromFile (url);
}
public static AssetBundleCreateRequest LoadAssetBundleFromFileAsync (string url)
{
if (!File.Exists (url)) {
if (_disk != null) {
var name = Path.GetFileName (url);
var file = _disk.GetFile (name, string.Empty);
if (file != null) {
return AssetBundle.LoadFromFileAsync (_disk.name, 0, (ulong)file.offset);
}
}
}
return AssetBundle.LoadFromFileAsync (url);
}
public static void BuildVersions (string outputPath, string[] bundles, int version)
{
var path = outputPath + "/" + Filename;
if (File.Exists (path)) {
File.Delete (path);
}
var dataPath = outputPath + "/" + Dataname;
if (File.Exists (dataPath)) {
File.Delete (dataPath);
}
var disk = new VDisk ();
foreach (var file in bundles) {
using (var fs = File.OpenRead (outputPath + "/" + file)) {
disk.AddFile (file, fs.Length, Utilitys.GetCRC32Hash (fs));
}
}
disk.name = dataPath;
disk.Save ();
using (var stream = File.OpenWrite (path)) {
var writer = new BinaryWriter (stream);
writer.Write (version);
writer.Write (disk.files.Count + 1);
using (var fs = File.OpenRead (dataPath)) {
var file = new VFile { name = Dataname, len = fs.Length, hash = Utilitys.GetCRC32Hash (fs) };
file.Serialize (writer);
}
foreach (var file in disk.files) {
file.Serialize (writer);
}
}
}
public static int LoadVersion (string filename)
{
if (!File.Exists (filename))
return -1;
try
{
using (var stream = File.OpenRead (filename)) {
var reader = new BinaryReader (stream);
if (reader.BaseStream.Position != reader.BaseStream.Length)
{
return reader.ReadInt32();
}
return -1;
}
}
catch (Exception e)
{
Debug.LogException(e);
return -1;
}
}
public static List<VFile> LoadVersions (string filename, bool update = false)
{
var rootDir = Path.GetDirectoryName(filename);
var data = update ? _updateData : _baseData;
data.Clear ();
using (var stream = File.OpenRead (filename)) {
var reader = new BinaryReader (stream);
var list = new List<VFile> ();
var ver = reader.ReadInt32 ();
Debug.Log ($"LoadVersions:{ver} \n{filename}");
var count = reader.ReadInt32 ();
for (var i = 0; i < count; i++) {
var version = new VFile ();
version.Deserialize (reader);
list.Add (version);
data [version.name] = version;
var dir = string.Format("{0}/{1}", rootDir, Path.GetDirectoryName(version.name));
if (! Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
}
return list;
}
}
public static void UpdateDisk(string savePath, List<VFile> newFiles)
{
var saveFiles = new List<VFile> ();
var files = _disk.files;
foreach (var file in files) {
if (_updateData.ContainsKey (file.name)) {
saveFiles.Add (file);
}
}
_disk.Update(savePath, newFiles, saveFiles);
}
public static bool LoadDisk (string filename)
{
return _disk.Load (filename);
}
public static bool IsNew (string path, long len, string hash)
{
VFile file;
var key = Path.GetFileName (path);
if (_baseData.TryGetValue (key, out file)) {
if (key.Equals (Dataname) ||
file.len == len && file.hash.Equals (hash, StringComparison.OrdinalIgnoreCase)) {
return false;
}
}
if (_disk.Exists ()) {
var vdf = _disk.GetFile (path, hash);
if (vdf != null && vdf.len == len && vdf.hash.Equals (hash, StringComparison.OrdinalIgnoreCase)) {
return false;
}
}
if (!File.Exists (path)) {
return true;
}
using (var stream = File.OpenRead (path)) {
if (stream.Length != len) {
return true;
}
if (verifyBy != VerifyBy.Hash)
return false;
return !Utilitys.GetCRC32Hash (stream).Equals (hash, StringComparison.OrdinalIgnoreCase);
}
}
}
}