This commit is contained in:
CortexCore
2024-03-31 23:31:00 +08:00
parent e179d2eb53
commit b7b89ee71a
641 changed files with 31286 additions and 22134 deletions

View File

@@ -0,0 +1,21 @@
{
"name": "BITKit.Mod.Runtime",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:d525ad6bd40672747bde77962f1c401e",
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
"GUID:f51ebe6a0ceec4240a699833d6309b23",
"GUID:e34a5702dd353724aa315fb8011f08c3",
"GUID:296866320aab85a42a0403bf684bac59"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": true,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f0b1819e72edd844b8a6538b7ae1cc42
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,70 @@
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using BITKit.IO;
using Cysharp.Threading.Tasks;
using UnityEngine;
using YooAsset;
namespace BITKit.Mod
{
public sealed class LoadAssetMod:MyMod
{
public override async UniTask OnInitializedAsync(CancellationToken cancellationToken)
{
var package = YooAssets.CreatePackage(PackageName);
var defaultHostServer = new RemoteServices(
$"file://{FolderPath}",FolderPath)
{
};
var queryServices = new LocalQueryServices($"{FolderPath}");
var initParameters = new HostPlayModeParameters
{
BuildinQueryServices = queryServices,
RemoteServices = defaultHostServer
};
var initOperation = package.InitializeAsync(initParameters);
await initOperation;
if(initOperation.Status == EOperationStatus.Succeed)
{
YooAssetUtils.RegisterPackage(PackageName);
var logBuilder = new StringBuilder();
logBuilder.AppendLine("该包中的资源:");
foreach (var x in package.GetAssetInfos(Tags))
{
logBuilder.AppendLine(x.Address);
}
logBuilder.AppendLine("默认包中的资源");
foreach (var x in YooAssets.GetAssetInfos(Tags))
{
logBuilder.AppendLine(x.Address);
}
BIT4Log.Log<UnityModLoadAssetTester>(logBuilder.ToString());
BIT4Log.Log<UnityModLoadAssetTester>($"资源包{PackageName}初始化成功!");
}
else
{
BIT4Log.Log<UnityModLoadAssetTester>($"资源包初始化失败:{initOperation.Error}");
}
}
public override void OnDispose()
{
YooAssets.DestroyPackage(PackageName);
}
public override void OnDisposed()
{
YooAssetUtils.UnregisterPackage(PackageName);
}
}
}

View File

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

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using BITKit.IO;
using Cysharp.Threading.Tasks;
using UnityEngine;
using YooAsset;
namespace BITKit.Mod
{
public class UnityModLoadAssetTester : MonoBehaviour
{
[SerializeField] private bool initOnStart;
[SerializeReference, SubclassSelector] private IReference packageName;
[SerializeReference, SubclassSelector] private IReference path;
[SerializeReference, SubclassSelector] private IReference[] testTag;
private void Start()
{
if (initOnStart)
{
Initialize();
}
}
[BIT]
private void Initialize()
{
var mod = new LoadAssetMod()
{
Name = "LoadAssetMod",
PackageName = packageName.Value,
FolderPath = $"file://{path.Value}" ,
Tags = testTag.Cast()
};
ModService.Install(mod);
ModService.Load(mod);
}
}
}

View File

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

View File

@@ -0,0 +1,147 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing.Printing;
using System.Text;
using BITKit.IO;
using Cysharp.Threading.Tasks;
using UnityEngine;
using YooAsset;
// ReSharper disable SuspiciousTypeConversion.Global
namespace BITKit.Mod
{
public class UnityModLoader : MonoBehaviour
{
private static readonly ConcurrentDictionary<string,IMod> _mods=new();
private static readonly ConcurrentDictionary<string,ResourcePackage> _packages=new();
private void OnEnable()
{
ModService.OnModLoadAsync += OnModLoadAsync;
ModService.OnModUnloadAsync += OnModUnloadAsync;
}
private void OnDisable()
{
ModService.OnModLoadAsync -= OnModLoadAsync;
ModService.OnModUnloadAsync -= OnModUnloadAsync;
}
private void OnDestroy()
{
_mods.Clear();
_packages.Clear();
}
private async UniTask OnModUnloadAsync(IMod mod)
{
switch (mod)
{
case IAssetMod:
_packages.TryRemove(mod.PackageName,out var package);
package.ClearPackageSandbox();
await package.ClearAllCacheFilesAsync();
await package.ClearUnusedCacheFilesAsync();
YooAssets.DestroyPackage(mod.PackageName);
YooAssetUtils.UnregisterPackage(mod.PackageName);
YooAssetUtils.UnregisterResourcePackage(_packages[mod.PackageName]);
break;
}
}
private async UniTask OnModLoadAsync(IMod arg)
{
try
{
switch (arg)
{
case IAssetMod:
var package = YooAssets.CreatePackage(arg.PackageName);
var defaultHostServer = new RemoteServices(
arg.FolderPath, arg.FolderPath)
{
};
var queryServices = new LocalQueryServices(arg.PackageName);
var initParameters = new HostPlayModeParameters
{
BuildinQueryServices = queryServices,
RemoteServices = defaultHostServer
};
var initOperation = package.InitializeAsync(initParameters);
await initOperation;
if(initOperation.Status!=EOperationStatus.Succeed)
{
throw new Exception(initOperation.Error);
}
var updateOperation = package.UpdatePackageVersionAsync(false);
await updateOperation;
if (updateOperation.Status != EOperationStatus.Succeed)
{
throw new Exception(updateOperation.Error);
}
var updateManifestOperation = package.UpdatePackageManifestAsync(updateOperation.PackageVersion, false);
await updateManifestOperation;
if(updateManifestOperation.Status!=EOperationStatus.Succeed)
{
throw new Exception(updateManifestOperation.Error);
}
var downloader = package.CreateResourceDownloader(8, 0);
downloader.BeginDownload();
await downloader;
if (downloader.Status != EOperationStatus.Succeed)
{
throw new Exception(downloader.Error);
}
_packages.TryAdd(arg.PackageName, package);
YooAssetUtils.RegisterResourcePackage(package);
YooAssetUtils.RegisterPackage(arg.PackageName);
// var logBuilder = new StringBuilder();
// logBuilder.AppendLine("该包中的资源:");
// foreach (var x in package.GetAssetInfos(arg.Tags))
// {
// logBuilder.AppendLine(x.Address);
// }
// logBuilder.AppendLine("默认包中的资源");
// foreach (var x in YooAssets.GetAssetInfos(arg.Tags))
// {
// logBuilder.AppendLine(x.Address);
// }
// BIT4Log.Log<UnityModLoadAssetTester>(logBuilder.ToString());
BIT4Log.Log<UnityModLoader>($"<color=green>资源包{arg.PackageName}初始化成功</color>");
break;
}
}
catch (Exception e)
{
BIT4Log.LogException(e);
}
}
}
}

View File

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

View File

@@ -0,0 +1,123 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BITKit.UX;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
namespace BITKit.Mod
{
public class UnityModService : MonoBehaviour
{
[SerializeReference,SubclassSelector] private IReference[] referencedAssemblies;
[SerializeField] private bool loadLocalPackageOnStart;
private async void Start()
{
DI.TryGet<IUXWaiting>(out var waiting);
var handle = waiting?.Get();
handle?.SetMessage("正在初始化Mod服务");
if (Application.isEditor is false)
{
BIT4Log.Log<UnityModService>($"UnityPlayer所在位置:{Application.dataPath}");
BIT4Log.Log<UnityModService>($"{nameof(System.Linq)}位于{typeof(Enumerable).Assembly.Location}");
}
foreach (var x in referencedAssemblies)
{
var dllName = x.Value.Contains(".dll") ? x.Value : $"{x.Value}.dll";
if (SearchDll(dllName,out var dll) is false)
{
BIT4Log.Warning<UnityModService>($"未找到:{dll}");
continue;
}
BITSharp.ReferencedAssemblies.Add(@$"""{dll}""");
}
try
{
ModService.Initialize();
}
catch (Exception e)
{
BIT4Log.Warning<UnityModService>("初始化失败");
BIT4Log.LogException(e);
return;
}
destroyCancellationToken.Register(ModService.Dispose);
if (!loadLocalPackageOnStart) return;
ModService.OnPackageLoad+=OnPackageLoad;
var packages = await ModService.SearchPackages();
if (destroyCancellationToken.IsCancellationRequested) return;
foreach (var package in packages)
{
await ModService.LoadFromPackage(package.PackagePath);
if (destroyCancellationToken.IsCancellationRequested) return;
}
destroyCancellationToken.Register(() =>
{
ModService.OnPackageLoad-=OnPackageLoad;
});
waiting?.Release(handle);
}
private void OnPackageLoad(ModPackage obj)
{
var loadedDlls = referencedAssemblies.Cast();
var reportBuilder = new System.Text.StringBuilder();
//对比已加载的dll和当前引用的dll
foreach (var x in obj.Dlls.Except(loadedDlls))
{
if (SearchDll(x, out var dll) is false)
{
BIT4Log.Warning<UnityModService>($"未找到:{dll}");
continue;
}
BITSharp.ReferencedAssemblies.Add(@$"""{dll}""");
reportBuilder.AppendLine($"加载:{dll}");
}
BIT4Log.Log<UnityModService>(reportBuilder.ToString());
}
private bool SearchDll(string dllName,out string dll,params string[] moreFolder)
{
#if UNITY_EDITOR
dll = System.IO.Path.Combine(Environment.CurrentDirectory, "Library", "ScriptAssemblies", dllName);
var folder = EditorApplication.applicationPath;
folder = Path.GetDirectoryName(folder);
if(File.Exists(dll) is false)
{
dll = Path.Combine(folder,"Data", "MonoBleedingEdge", "lib","mono","unityjit-win32",dllName);
}
if (File.Exists(dll) is false)
{
dll = Path.Combine(folder,"Data", "MonoBleedingEdge", "lib","mono","unityjit-win32","Facades",dllName);
}
#else
dll = System.IO.Path.Combine(Environment.CurrentDirectory,$"{Application.productName}_Data", "Managed", dllName);
#endif
return File.Exists(dll);
}
}
}

View File

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

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
namespace BITKit.Mod
{
public class UnityModServiceTester : MonoBehaviour
{
[Serializable]
public class TestLogGameTickMod:MyMod
{
public override void OnInitialized()
{
base.OnInitialized();
GameTickService.Add(OnTick);
}
private static void OnTick(float obj)
{
BIT4Log.Log<TestLogGameTickMod>($"On Test Mod Tick,delta:{obj}");
}
public override void OnDispose()
{
GameTickService.Remove(OnTick);
}
}
[SerializeReference, SubclassSelector] private IMod[] initialMods;
private void OnEnable()
{
foreach (var testMod in initialMods)
{
ModService.Install(testMod);
ModService.Load(testMod);
}
}
private void OnDisable()
{
foreach (var testMod in initialMods)
{
ModService.UnLoad(testMod);
ModService.UnInstall(testMod);
}
}
}
}

View File

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

View File

@@ -0,0 +1,62 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using BITKit.Net.LAN;
using Cysharp.Threading.Tasks;
using UnityEngine;
namespace BITKit.Mod
{
public class UnityWorkshopClient : MonoBehaviour
{
[SerializeField] private int port;
private UdpBasedLanBroadcaster _broadcaster;
private void Start()
{
_broadcaster = new UdpBasedLanBroadcaster
{
Port = port
};
_broadcaster.OnReceive += OnReceive;
_broadcaster.StartListen();
}
private async void OnReceive(EndPoint arg1, byte[] bytes)
{
await UniTask.SwitchToMainThread();
if(destroyCancellationToken.IsCancellationRequested) return;
var command = BITBinary.ReadAsValue(bytes);
switch (command)
{
case LoadFromFolderCommand loadFromFolderCommand:
BIT4Log.Log<UnityWorkshopClient>($"收到加载命令:{loadFromFolderCommand.FolderPath}");
ModService.LoadFromPackage(loadFromFolderCommand.FolderPath).Forget();
break;
case UninstallPackageCommand uninstallPackageCommand:
BIT4Log.Log<UnityWorkshopClient>($"收到卸载命令:{uninstallPackageCommand.PackageName}");
var mod = ModService.Mods.SingleOrDefault(x=>x.PackageName == uninstallPackageCommand.PackageName);
if (mod is null)
{
BIT4Log.Warning<UnityWorkshopClient>($"未找到包:{uninstallPackageCommand.PackageName}");
return;
}
ModService.UnLoad(mod);
ModService.UnInstall(mod);
break;
default:
BIT4Log.Log<UnityWorkshopClient>($"未知命令:{command}");
break;
}
}
private void OnDestroy()
{
if (_broadcaster is not null)
_broadcaster.Dispose();
}
}
}

View File

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