初始化仓库
This commit is contained in:
@@ -0,0 +1,293 @@
|
||||
//------------------------------------------------------------
|
||||
// Game Framework
|
||||
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
|
||||
// Homepage: https://gameframework.cn/
|
||||
// Feedback: mailto:ellan@gameframework.cn
|
||||
//------------------------------------------------------------
|
||||
|
||||
using GameFramework;
|
||||
using GameFramework.FileSystem;
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityGameFramework.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// 安卓文件系统流。
|
||||
/// </summary>
|
||||
public sealed class AndroidFileSystemStream : FileSystemStream
|
||||
{
|
||||
private static readonly string SplitFlag = "!/assets/";
|
||||
private static readonly int SplitFlagLength = SplitFlag.Length;
|
||||
private static readonly AndroidJavaObject s_AssetManager = null;
|
||||
private static readonly IntPtr s_InternalReadMethodId = IntPtr.Zero;
|
||||
private static readonly jvalue[] s_InternalReadArgs = null;
|
||||
|
||||
private readonly AndroidJavaObject m_FileStream;
|
||||
private readonly IntPtr m_FileStreamRawObject;
|
||||
|
||||
static AndroidFileSystemStream()
|
||||
{
|
||||
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
|
||||
if (unityPlayer == null)
|
||||
{
|
||||
throw new GameFrameworkException("Unity player is invalid.");
|
||||
}
|
||||
|
||||
AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
|
||||
if (currentActivity == null)
|
||||
{
|
||||
throw new GameFrameworkException("Current activity is invalid.");
|
||||
}
|
||||
|
||||
AndroidJavaObject assetManager = currentActivity.Call<AndroidJavaObject>("getAssets");
|
||||
if (assetManager == null)
|
||||
{
|
||||
throw new GameFrameworkException("Asset manager is invalid.");
|
||||
}
|
||||
|
||||
s_AssetManager = assetManager;
|
||||
|
||||
IntPtr inputStreamClassPtr = AndroidJNI.FindClass("java/io/InputStream");
|
||||
s_InternalReadMethodId = AndroidJNIHelper.GetMethodID(inputStreamClassPtr, "read", "([BII)I");
|
||||
s_InternalReadArgs = new jvalue[3];
|
||||
|
||||
AndroidJNI.DeleteLocalRef(inputStreamClassPtr);
|
||||
currentActivity.Dispose();
|
||||
unityPlayer.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化安卓文件系统流的新实例。
|
||||
/// </summary>
|
||||
/// <param name="fullPath">要加载的文件系统的完整路径。</param>
|
||||
/// <param name="access">要加载的文件系统的访问方式。</param>
|
||||
/// <param name="createNew">是否创建新的文件系统流。</param>
|
||||
public AndroidFileSystemStream(string fullPath, FileSystemAccess access, bool createNew)
|
||||
{
|
||||
if (string.IsNullOrEmpty(fullPath))
|
||||
{
|
||||
throw new GameFrameworkException("Full path is invalid.");
|
||||
}
|
||||
|
||||
if (access != FileSystemAccess.Read)
|
||||
{
|
||||
throw new GameFrameworkException(Utility.Text.Format("'{0}' is not supported in AndroidFileSystemStream.", access));
|
||||
}
|
||||
|
||||
if (createNew)
|
||||
{
|
||||
throw new GameFrameworkException("Create new is not supported in AndroidFileSystemStream.");
|
||||
}
|
||||
|
||||
int position = fullPath.LastIndexOf(SplitFlag, StringComparison.Ordinal);
|
||||
if (position < 0)
|
||||
{
|
||||
throw new GameFrameworkException("Can not find split flag in full path.");
|
||||
}
|
||||
|
||||
string fileName = fullPath.Substring(position + SplitFlagLength);
|
||||
m_FileStream = InternalOpen(fileName);
|
||||
if (m_FileStream == null)
|
||||
{
|
||||
throw new GameFrameworkException(Utility.Text.Format("Open file '{0}' from Android asset manager failure.", fullPath));
|
||||
}
|
||||
|
||||
m_FileStreamRawObject = m_FileStream.GetRawObject();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置文件系统流位置。
|
||||
/// </summary>
|
||||
protected override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new GameFrameworkException("Get position is not supported in AndroidFileSystemStream.");
|
||||
}
|
||||
set
|
||||
{
|
||||
Seek(value, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取文件系统流长度。
|
||||
/// </summary>
|
||||
protected override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return InternalAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置文件系统流长度。
|
||||
/// </summary>
|
||||
/// <param name="length">要设置的文件系统流的长度。</param>
|
||||
protected override void SetLength(long length)
|
||||
{
|
||||
throw new GameFrameworkException("SetLength is not supported in AndroidFileSystemStream.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定位文件系统流位置。
|
||||
/// </summary>
|
||||
/// <param name="offset">要定位的文件系统流位置的偏移。</param>
|
||||
/// <param name="origin">要定位的文件系统流位置的方式。</param>
|
||||
protected override void Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
if (origin == SeekOrigin.End)
|
||||
{
|
||||
Seek(Length + offset, SeekOrigin.Begin);
|
||||
return;
|
||||
}
|
||||
|
||||
if (origin == SeekOrigin.Begin)
|
||||
{
|
||||
InternalReset();
|
||||
}
|
||||
|
||||
while (offset > 0)
|
||||
{
|
||||
long skip = InternalSkip(offset);
|
||||
if (skip < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
offset -= skip;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从文件系统流中读取一个字节。
|
||||
/// </summary>
|
||||
/// <returns>读取的字节,若已经到达文件结尾,则返回 -1。</returns>
|
||||
protected override int ReadByte()
|
||||
{
|
||||
return InternalRead();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从文件系统流中读取二进制流。
|
||||
/// </summary>
|
||||
/// <param name="buffer">存储读取文件内容的二进制流。</param>
|
||||
/// <param name="startIndex">存储读取文件内容的二进制流的起始位置。</param>
|
||||
/// <param name="length">存储读取文件内容的二进制流的长度。</param>
|
||||
/// <returns>实际读取了多少字节。</returns>
|
||||
protected override int Read(byte[] buffer, int startIndex, int length)
|
||||
{
|
||||
byte[] result = null;
|
||||
int bytesRead = InternalRead(length, out result);
|
||||
Array.Copy(result, 0, buffer, startIndex, bytesRead);
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向文件系统流中写入一个字节。
|
||||
/// </summary>
|
||||
/// <param name="value">要写入的字节。</param>
|
||||
protected override void WriteByte(byte value)
|
||||
{
|
||||
throw new GameFrameworkException("WriteByte is not supported in AndroidFileSystemStream.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向文件系统流中写入二进制流。
|
||||
/// </summary>
|
||||
/// <param name="buffer">存储写入文件内容的二进制流。</param>
|
||||
/// <param name="startIndex">存储写入文件内容的二进制流的起始位置。</param>
|
||||
/// <param name="length">存储写入文件内容的二进制流的长度。</param>
|
||||
protected override void Write(byte[] buffer, int startIndex, int length)
|
||||
{
|
||||
throw new GameFrameworkException("Write is not supported in AndroidFileSystemStream.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将文件系统流立刻更新到存储介质中。
|
||||
/// </summary>
|
||||
protected override void Flush()
|
||||
{
|
||||
throw new GameFrameworkException("Flush is not supported in AndroidFileSystemStream.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭文件系统流。
|
||||
/// </summary>
|
||||
protected override void Close()
|
||||
{
|
||||
InternalClose();
|
||||
m_FileStream.Dispose();
|
||||
}
|
||||
|
||||
private AndroidJavaObject InternalOpen(string fileName)
|
||||
{
|
||||
return s_AssetManager.Call<AndroidJavaObject>("open", fileName);
|
||||
}
|
||||
|
||||
private int InternalAvailable()
|
||||
{
|
||||
return m_FileStream.Call<int>("available");
|
||||
}
|
||||
|
||||
private void InternalClose()
|
||||
{
|
||||
m_FileStream.Call("close");
|
||||
}
|
||||
|
||||
private int InternalRead()
|
||||
{
|
||||
return m_FileStream.Call<int>("read");
|
||||
}
|
||||
|
||||
private int InternalRead(int length, out byte[] result)
|
||||
{
|
||||
#if UNITY_2019_2_OR_NEWER
|
||||
#pragma warning disable CS0618
|
||||
#endif
|
||||
IntPtr resultPtr = AndroidJNI.NewByteArray(length);
|
||||
#if UNITY_2019_2_OR_NEWER
|
||||
#pragma warning restore CS0618
|
||||
#endif
|
||||
int offset = 0;
|
||||
int bytesLeft = length;
|
||||
while (bytesLeft > 0)
|
||||
{
|
||||
s_InternalReadArgs[0] = new jvalue() { l = resultPtr };
|
||||
s_InternalReadArgs[1] = new jvalue() { i = offset };
|
||||
s_InternalReadArgs[2] = new jvalue() { i = bytesLeft };
|
||||
int bytesRead = AndroidJNI.CallIntMethod(m_FileStreamRawObject, s_InternalReadMethodId, s_InternalReadArgs);
|
||||
if (bytesRead <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
offset += bytesRead;
|
||||
bytesLeft -= bytesRead;
|
||||
}
|
||||
|
||||
#if UNITY_2019_2_OR_NEWER
|
||||
#pragma warning disable CS0618
|
||||
#endif
|
||||
result = AndroidJNI.FromByteArray(resultPtr);
|
||||
#if UNITY_2019_2_OR_NEWER
|
||||
#pragma warning restore CS0618
|
||||
#endif
|
||||
AndroidJNI.DeleteLocalRef(resultPtr);
|
||||
return offset;
|
||||
}
|
||||
|
||||
private void InternalReset()
|
||||
{
|
||||
m_FileStream.Call("reset");
|
||||
}
|
||||
|
||||
private long InternalSkip(long offset)
|
||||
{
|
||||
return m_FileStream.Call<long>("skip", offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e91d57307e5c7674c855d299cfb466b6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,39 @@
|
||||
//------------------------------------------------------------
|
||||
// Game Framework
|
||||
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
|
||||
// Homepage: https://gameframework.cn/
|
||||
// Feedback: mailto:ellan@gameframework.cn
|
||||
//------------------------------------------------------------
|
||||
|
||||
using GameFramework.FileSystem;
|
||||
using System;
|
||||
|
||||
namespace UnityGameFramework.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认文件系统辅助器。
|
||||
/// </summary>
|
||||
public class DefaultFileSystemHelper : FileSystemHelperBase
|
||||
{
|
||||
private const string AndroidFileSystemPrefixString = "jar:";
|
||||
|
||||
/// <summary>
|
||||
/// 创建文件系统流。
|
||||
/// </summary>
|
||||
/// <param name="fullPath">要加载的文件系统的完整路径。</param>
|
||||
/// <param name="access">要加载的文件系统的访问方式。</param>
|
||||
/// <param name="createNew">是否创建新的文件系统流。</param>
|
||||
/// <returns>创建的文件系统流。</returns>
|
||||
public override FileSystemStream CreateFileSystemStream(string fullPath, FileSystemAccess access, bool createNew)
|
||||
{
|
||||
if (fullPath.StartsWith(AndroidFileSystemPrefixString, StringComparison.Ordinal))
|
||||
{
|
||||
return new AndroidFileSystemStream(fullPath, access, createNew);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new CommonFileSystemStream(fullPath, access, createNew);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab61553d44f971447856311f2f7aef44
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,146 @@
|
||||
//------------------------------------------------------------
|
||||
// Game Framework
|
||||
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
|
||||
// Homepage: https://gameframework.cn/
|
||||
// Feedback: mailto:ellan@gameframework.cn
|
||||
//------------------------------------------------------------
|
||||
|
||||
using GameFramework;
|
||||
using GameFramework.FileSystem;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityGameFramework.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件系统件。
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
[AddComponentMenu("Game Framework/File System")]
|
||||
public sealed class FileSystemComponent : GameFrameworkComponent
|
||||
{
|
||||
private IFileSystemManager m_FileSystemManager = null;
|
||||
|
||||
[SerializeField]
|
||||
private string m_FileSystemHelperTypeName = "UnityGameFramework.Runtime.DefaultFileSystemHelper";
|
||||
|
||||
[SerializeField]
|
||||
private FileSystemHelperBase m_CustomFileSystemHelper = null;
|
||||
|
||||
/// <summary>
|
||||
/// 获取文件系统数量。
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_FileSystemManager.Count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 游戏框架组件初始化。
|
||||
/// </summary>
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
m_FileSystemManager = GameFrameworkEntry.GetModule<IFileSystemManager>();
|
||||
if (m_FileSystemManager == null)
|
||||
{
|
||||
Log.Fatal("File system manager is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
FileSystemHelperBase fileSystemHelper = Helper.CreateHelper(m_FileSystemHelperTypeName, m_CustomFileSystemHelper);
|
||||
if (fileSystemHelper == null)
|
||||
{
|
||||
Log.Error("Can not create fileSystem helper.");
|
||||
return;
|
||||
}
|
||||
|
||||
fileSystemHelper.name = "FileSystem Helper";
|
||||
Transform transform = fileSystemHelper.transform;
|
||||
transform.SetParent(this.transform);
|
||||
transform.localScale = Vector3.one;
|
||||
|
||||
m_FileSystemManager.SetFileSystemHelper(fileSystemHelper);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否存在文件系统。
|
||||
/// </summary>
|
||||
/// <param name="fullPath">要检查的文件系统的完整路径。</param>
|
||||
/// <returns>是否存在文件系统。</returns>
|
||||
public bool HasFileSystem(string fullPath)
|
||||
{
|
||||
return m_FileSystemManager.HasFileSystem(fullPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取文件系统。
|
||||
/// </summary>
|
||||
/// <param name="fullPath">要获取的文件系统的完整路径。</param>
|
||||
/// <returns>获取的文件系统。</returns>
|
||||
public IFileSystem GetFileSystem(string fullPath)
|
||||
{
|
||||
return m_FileSystemManager.GetFileSystem(fullPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建文件系统。
|
||||
/// </summary>
|
||||
/// <param name="fullPath">要创建的文件系统的完整路径。</param>
|
||||
/// <param name="access">要创建的文件系统的访问方式。</param>
|
||||
/// <param name="maxFileCount">要创建的文件系统的最大文件数量。</param>
|
||||
/// <param name="maxBlockCount">要创建的文件系统的最大块数据数量。</param>
|
||||
/// <returns>创建的文件系统。</returns>
|
||||
public IFileSystem CreateFileSystem(string fullPath, FileSystemAccess access, int maxFileCount, int maxBlockCount)
|
||||
{
|
||||
return m_FileSystemManager.CreateFileSystem(fullPath, access, maxFileCount, maxBlockCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载文件系统。
|
||||
/// </summary>
|
||||
/// <param name="fullPath">要加载的文件系统的完整路径。</param>
|
||||
/// <param name="access">要加载的文件系统的访问方式。</param>
|
||||
/// <returns>加载的文件系统。</returns>
|
||||
public IFileSystem LoadFileSystem(string fullPath, FileSystemAccess access)
|
||||
{
|
||||
return m_FileSystemManager.LoadFileSystem(fullPath, access);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁文件系统。
|
||||
/// </summary>
|
||||
/// <param name="fileSystem">要销毁的文件系统。</param>
|
||||
/// <param name="deletePhysicalFile">是否删除文件系统对应的物理文件。</param>
|
||||
public void DestroyFileSystem(IFileSystem fileSystem, bool deletePhysicalFile)
|
||||
{
|
||||
m_FileSystemManager.DestroyFileSystem(fileSystem, deletePhysicalFile);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有文件系统集合。
|
||||
/// </summary>
|
||||
/// <returns>获取的所有文件系统集合。</returns>
|
||||
public IFileSystem[] GetAllFileSystems()
|
||||
{
|
||||
return m_FileSystemManager.GetAllFileSystems();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有文件系统集合。
|
||||
/// </summary>
|
||||
/// <param name="results">获取的所有文件系统集合。</param>
|
||||
public void GetAllFileSystems(List<IFileSystem> results)
|
||||
{
|
||||
m_FileSystemManager.GetAllFileSystems(results);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc49d78dad061a2418e134fc48856bc9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,27 @@
|
||||
//------------------------------------------------------------
|
||||
// Game Framework
|
||||
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
|
||||
// Homepage: https://gameframework.cn/
|
||||
// Feedback: mailto:ellan@gameframework.cn
|
||||
//------------------------------------------------------------
|
||||
|
||||
using GameFramework.FileSystem;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityGameFramework.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件系统辅助器基类。
|
||||
/// </summary>
|
||||
public abstract class FileSystemHelperBase : MonoBehaviour, IFileSystemHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建文件系统流。
|
||||
/// </summary>
|
||||
/// <param name="fullPath">要加载的文件系统的完整路径。</param>
|
||||
/// <param name="access">要加载的文件系统的访问方式。</param>
|
||||
/// <param name="createNew">是否创建新的文件系统流。</param>
|
||||
/// <returns>创建的文件系统流。</returns>
|
||||
public abstract FileSystemStream CreateFileSystemStream(string fullPath, FileSystemAccess access, bool createNew);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 40934320d6b918548891a29641dc0a20
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user