first commit

This commit is contained in:
2025-07-06 00:23:46 +02:00
commit 38f50c8819
1788 changed files with 112878 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
using AssetsTools.NET;
using NitroxModel.DataStructures.Unity;
using UnityEngine;
namespace NitroxServer_Subnautica.Resources.Parsers.Helper;
public static class AssetTypeValueFieldExtension
{
public static Vector3 ToVector3(this AssetTypeValueField valueField)
{
return new Vector3(valueField["x"].AsFloat, valueField["y"].AsFloat, valueField["z"].AsFloat);
}
public static NitroxVector3 ToNitroxVector3(this AssetTypeValueField valueField)
{
return new NitroxVector3(valueField["x"].AsFloat, valueField["y"].AsFloat, valueField["z"].AsFloat);
}
public static NitroxQuaternion ToNitroxQuaternion(this AssetTypeValueField valueField)
{
return new NitroxQuaternion(valueField["x"].AsFloat, valueField["y"].AsFloat, valueField["z"].AsFloat, valueField["w"].AsFloat);
}
}

View File

@@ -0,0 +1,147 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using AssetsTools.NET;
using AssetsTools.NET.Extra;
using NitroxModel.DataStructures.Unity;
namespace NitroxServer_Subnautica.Resources.Parsers.Helper;
public class AssetsBundleManager : AssetsManager
{
private readonly string aaRootPath;
private readonly Dictionary<AssetsFileInstance, string[]> dependenciesByAssetFileInst = new();
private ThreadSafeMonoCecilTempGenerator monoTempGenerator;
public AssetsBundleManager(string aaRootPath)
{
this.aaRootPath = aaRootPath;
}
public string CleanBundlePath(string bundlePath)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
bundlePath = bundlePath.Replace('\\', '/');
}
return aaRootPath + bundlePath.Substring(bundlePath.IndexOf('}') + 1);
}
public AssetsFileInstance LoadBundleWithDependencies(string[] bundlePaths)
{
BundleFileInstance bundleFile = LoadBundleFile(CleanBundlePath(bundlePaths[0]));
AssetsFileInstance assetFileInstance = LoadAssetsFileFromBundle(bundleFile, 0);
dependenciesByAssetFileInst[assetFileInstance] = bundlePaths;
return assetFileInstance;
}
/// <summary>
/// Copied from https://github.com/nesrak1/AssetsTools.NET#full-monobehaviour-writing-example
/// </summary>
/// <param name="inst"><see cref="AssetsFileInstance" /> instance currently used</param>
/// <param name="targetGameObjectValue"><see cref="AssetFileInfo" /> of the target GameObject</param>
/// <param name="targetClassName">Class name of the target MonoBehaviour</param>
public AssetFileInfo GetMonoBehaviourFromGameObject(AssetsFileInstance inst, AssetFileInfo targetGameObjectValue, string targetClassName)
{
//example for finding a specific script and modifying the script on a GameObject
AssetTypeValueField playerBf = GetBaseField(inst, targetGameObjectValue);
AssetTypeValueField playerComponentArr = playerBf["m_Component"]["Array"];
AssetFileInfo monoBehaviourInf = null;
//first let's search for the MonoBehaviour we want in a GameObject
foreach (AssetTypeValueField child in playerComponentArr.Children)
{
//get component info (but don't deserialize yet, loading assets we don't need is wasteful)
AssetTypeValueField childPtr = child["component"];
AssetExternal childExt = GetExtAsset(inst, childPtr, true);
AssetFileInfo childInf = childExt.info;
//skip if not MonoBehaviour
if (childInf.GetTypeId(inst.file) != (int)AssetClassID.MonoBehaviour)
{
continue;
}
//actually deserialize the MonoBehaviour asset now
AssetTypeValueField childBf = GetExtAssetSafe(inst, childPtr).baseField;
AssetTypeValueField monoScriptPtr = childBf["m_Script"];
//get MonoScript from MonoBehaviour
AssetExternal monoScriptExt = GetExtAsset(childExt.file, monoScriptPtr);
AssetTypeValueField monoScriptBf = monoScriptExt.baseField;
string className = monoScriptBf["m_ClassName"].AsString;
if (className == targetClassName)
{
monoBehaviourInf = childInf;
break;
}
}
return monoBehaviourInf;
}
public NitroxTransform GetTransformFromGameObject(AssetsFileInstance assetFileInst, AssetTypeValueField rootGameObject)
{
AssetTypeValueField componentArray = rootGameObject["m_Component"]["Array"];
AssetTypeValueField transformRef = componentArray[0]["component"];
AssetTypeValueField transformField = GetExtAsset(assetFileInst, transformRef).baseField;
return new(transformField["m_LocalPosition"].ToNitroxVector3(), transformField["m_LocalRotation"].ToNitroxQuaternion(), transformField["m_LocalScale"].ToNitroxVector3());
}
public new void SetMonoTempGenerator(IMonoBehaviourTemplateGenerator generator)
{
monoTempGenerator = (ThreadSafeMonoCecilTempGenerator)generator;
base.SetMonoTempGenerator(generator);
}
/// <summary>
/// Returns a ready to use <see cref="AssetsManager" /> with loaded <see cref="AssetsManager.classDatabase" />, <see cref="AssetsManager.classPackage" /> and
/// <see cref="IMonoBehaviourTemplateGenerator" />.
/// </summary>
public AssetsBundleManager Clone()
{
AssetsBundleManager bundleManagerInst = new(aaRootPath) { classDatabase = classDatabase, classPackage = classPackage };
bundleManagerInst.SetMonoTempGenerator(monoTempGenerator);
return bundleManagerInst;
}
/// <inheritdoc cref="AssetsManager.UnloadAll" />
public new void UnloadAll(bool unloadClassData = false)
{
if (unloadClassData)
{
monoTempGenerator.Dispose();
}
dependenciesByAssetFileInst.Clear();
base.UnloadAll(unloadClassData);
}
private AssetExternal GetExtAssetSafe(AssetsFileInstance relativeTo, AssetTypeValueField valueField)
{
string[] bundlePaths = dependenciesByAssetFileInst[relativeTo];
for (int i = 0; i < bundlePaths.Length; i++)
{
if (i != 0)
{
BundleFileInstance dependenciesBundleFile = LoadBundleFile(CleanBundlePath(bundlePaths[i]));
LoadAssetsFileFromBundle(dependenciesBundleFile, 0);
}
try
{
return GetExtAsset(relativeTo, valueField);
}
catch (Exception)
{
// ignored
}
}
throw new InvalidOperationException("Could find AssetTypeValueField in given dependencies");
}
}

View File

@@ -0,0 +1,19 @@
using AssetsTools.NET;
using AssetsTools.NET.Extra;
namespace NitroxServer_Subnautica.Resources.Parsers.Helper;
public static class AssetsFileMetadataExtension
{
public static AssetFileInfo GetAssetInfo(this AssetsFile assetsFile, AssetsManager assetsManager, string assetName, AssetClassID classID)
{
foreach (AssetFileInfo assetInfo in assetsFile.GetAssetsOfType(classID))
{
if (AssetHelper.GetAssetNameFast(assetsFile, assetsManager.classDatabase, assetInfo).Equals(assetName))
{
return assetInfo;
}
}
return null;
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Threading;
using AssetsTools.NET;
using AssetsTools.NET.Extra;
using Mono.Cecil;
namespace NitroxServer_Subnautica.Resources.Parsers.Helper;
public class ThreadSafeMonoCecilTempGenerator : IMonoBehaviourTemplateGenerator, IDisposable
{
private readonly MonoCecilTempGenerator generator;
private readonly Lock locker = new();
public ThreadSafeMonoCecilTempGenerator(string managedPath)
{
generator = new MonoCecilTempGenerator(managedPath);
}
public AssetTypeTemplateField GetTemplateField(
AssetTypeTemplateField baseField,
string assemblyName,
string nameSpace,
string className,
UnityVersion unityVersion)
{
lock (locker)
{
return generator.GetTemplateField(baseField, assemblyName, nameSpace, className, unityVersion);
}
}
public void Dispose()
{
foreach (KeyValuePair<string, AssemblyDefinition> pair in generator.loadedAssemblies)
{
pair.Value.Dispose();
}
generator.loadedAssemblies.Clear();
}
}