Skip to content

Commit

Permalink
remove ecclib
Browse files Browse the repository at this point in the history
cache FMODAssets (removes a teeny-tiny memory leak)
update readme a bit while we're at it
  • Loading branch information
Govorunb committed Jun 19, 2024
1 parent 9319ef9 commit a45e946
Show file tree
Hide file tree
Showing 21 changed files with 212 additions and 5,187 deletions.
1 change: 0 additions & 1 deletion BelowZero.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

<ItemGroup>
<Reference Include="../Dependencies/BelowZero/FMODUnity.dll" />
<Reference Include="../Install/BelowZero/BepInEx/plugins/ECCLibrary/ECCLibrary.dll" />
</ItemGroup>

<ItemGroup>
Expand Down
Binary file not shown.
2,533 changes: 0 additions & 2,533 deletions Install/BelowZero/BepInEx/plugins/ECCLibrary/ECCLibrary.xml

This file was deleted.

Binary file not shown.
2,562 changes: 0 additions & 2,562 deletions Install/Subnautica/BepInEx/plugins/ECCLibrary/ECCLibrary.xml

This file was deleted.

82 changes: 42 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,47 @@
## Neurosama-Subnautica-Mod
Mod for Subnautica and Subnautica Below Zero, as seen on [vedal987](https://twitch.tv/vedal987)'s streams
Mod for [Subnautica](https://store.steampowered.com/app/264710/Subnautica/)
and [Subnautica: Below Zero](https://store.steampowered.com/app/848450/Subnautica_Below_Zero/),
as seen on [vedal987](https://twitch.tv/vedal987)'s streams

Requires BepInEx, Nautilus and ECCLibrary to run
Mod dependencies:
- [BepInEx Mono v5.4.23](https://github.com/BepInEx/BepInEx/releases/tag/v5.4.23.2) (not compatible with v6)
- [Nautilus 1.0.0-pre.29](https://github.com/SubnauticaModding/Nautilus/releases/tag/1.0.0-pre.29) (later 1.0.0 versions should work)

Please note that a custom version of ECCLibrary is used!
### Credits (currently outdated)

### Credits
["2Pfrog"] = Credits.Artist,
["AlexejheroDev"] = Credits.Programming + Credits.ProjectLead,
["Azit"] = Credits.Artist,
["baa14453"] = Credits.Lore,
["bred"] = Credits.Modeling + Credits.Texturing + Credits.Animations,
["budwheizzah"] = Credits.Programming + Credits.Artist + Credits.Sounds,
["chrom"] = Credits.Artist,
["CJMAXiK"] = Credits.Artist + Credits.Sounds,
["darkeew"] = Credits.Contributor,
["FutabaKuuhaku"] = Credits.Modeling + Credits.Texturing,
["Goldenbeasty"] = Credits.Texturing,
["Govorunb"] = Credits.Programming,
["greencap"] = Credits.Modeling + Credits.Texturing,
["Hakuhan"] = Credits.Artist,
["Kat"] = Credits.Modeling + Credits.Texturing,
["Kaz"] = Credits.Artist,
["Lorx"] = Credits.Artist,
["Moloch"] = Credits.Artist,
["MyBraza"] = Credits.Artist + Credits.Sounds,
["NetPlayz"] = Credits.Artist,
["P3R"] = Credits.Artist,
["paccha"] = Credits.Artist,
["Rune"] = Credits.Artist,
["SADecsSs"] = Credits.Artist,
["Sandro"] = Credits.Artist,
["SomeOldGuy"] = Credits.Artist,
["sugarph"] = Credits.Artist,
["Troobs"] = Credits.Artist,
["Vaalmyr"] = Credits.Modeling + Credits.Texturing,
["vanorsigma"] = Credits.Contributor,
["w1n7er"] = Credits.Modeling + Credits.Texturing + Credits.Animations,
["yamplum"] = Credits.Artist + Credits.Lore,
["YuG"] = Credits.Modeling + Credits.Texturing,

["2Pfrog"] = Credits.Artist,
["AlexejheroDev"] = Credits.Programming + Credits.ProjectLead,
["Azit"] = Credits.Artist,
["baa14453"] = Credits.Lore,
["bred"] = Credits.Modeling + Credits.Texturing + Credits.Animations,
["budwheizzah"] = Credits.Programming + Credits.Artist + Credits.Sounds,
["chrom"] = Credits.Artist,
["CJMAXiK"] = Credits.Artist + Credits.Sounds,
["darkeew"] = Credits.Contributor,
["FutabaKuuhaku"] = Credits.Modeling + Credits.Texturing,
["Goldenbeasty"] = Credits.Texturing,
["Govorunb"] = Credits.Programming,
["greencap"] = Credits.Modeling + Credits.Texturing,
["Hakuhan"] = Credits.Artist,
["Kat"] = Credits.Modeling + Credits.Texturing,
["Kaz"] = Credits.Artist,
["Lorx"] = Credits.Artist,
["Moloch"] = Credits.Artist,
["MyBraza"] = Credits.Artist + Credits.Sounds,
["NetPlayz"] = Credits.Artist,
["P3R"] = Credits.Artist,
["paccha"] = Credits.Artist,
["Rune"] = Credits.Artist,
["SADecsSs"] = Credits.Artist,
["Sandro"] = Credits.Artist,
["SomeOldGuy"] = Credits.Artist,
["sugarph"] = Credits.Artist,
["Troobs"] = Credits.Artist,
["Vaalmyr"] = Credits.Modeling + Credits.Texturing,
["vanorsigma"] = Credits.Contributor,
["w1n7er"] = Credits.Modeling + Credits.Texturing + Credits.Animations,
["yamplum"] = Credits.Artist + Credits.Lore,
["YuG"] = Credits.Modeling + Credits.Texturing,

Based on ahk1221's Custom Hull Plates mod<br>
Using Lee23's ECCLibrary mod
Hull plates code based on ahk1221's [Custom Hull Plates](https://github.com/MrPurple6411/My-Subnautica-Mods/tree/main/CustomHullPlates) mod<br>
Using code based on Lee23's [ECCLibrary](https://github.com/LeeTwentyThree/ECCLibrary/releases/latest) mod
23 changes: 12 additions & 11 deletions SCHIZO/Commands/FMODCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using FMODUnity;
using SCHIZO.Commands.Attributes;
using SCHIZO.Commands.Base;
using SCHIZO.Commands.Output;
using SCHIZO.Helpers;
using UnityEngine;

Expand All @@ -15,17 +16,17 @@ namespace SCHIZO.Commands;
DisplayName = "FMOD",
Description = "Commands for working with FMOD",
RegisterConsoleCommand = true
)]
)]
public class FMODCommand : CompositeCommand
{
[SubCommand]
public static string Play(string pathOrGuid, float distance = 0)
public static object Play(string pathOrGuid, float distance = 0)
{
if (Guid.TryParse(pathOrGuid, out Guid guid))
pathOrGuid = GetPath(guid.ToString());
pathOrGuid = FMODHelpers.GetPath(guid);

if (string.IsNullOrEmpty(pathOrGuid))
return "Null sound path";
return CommonResults.Error("Null sound path");

try
{
Expand All @@ -39,17 +40,17 @@ public static string Play(string pathOrGuid, float distance = 0)
Vector3 pos = Camera.main.transform.position + deltaPos;
RuntimeManager.PlayOneShot(pathOrGuid, pos);
}
return null;
return CommonResults.OK();
}
catch (EventNotFoundException e)
catch (EventNotFoundException)
{
return $"FMOD event not found: {e.Message}";
return CommonResults.Error($"FMOD event not found: {pathOrGuid}");
}
}
[SubCommand]
public static string GetPath(string guid) => FMODHelpers.GetPath(guid);
[SubCommand]
public static string GetId(string path) => FMODHelpers.GetId(path);
[SubCommand(NameOverride = "path")]
public static object GetPath(string guid) => (object)FMODHelpers.GetPath(guid) ?? CommonResults.Error("Not found");
[SubCommand(NameOverride = "id")]
public static object GetId(string path) => (object)FMODHelpers.GetId(path) ?? CommonResults.Error("Not found");

// all of these were adapted from https://discord.com/channels/324207629784186882/324207629784186882/1065010826571956294
[SubCommand]
Expand Down
9 changes: 8 additions & 1 deletion SCHIZO/Creatures/Components/CreaturePhysicMaterial.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@ namespace SCHIZO.Creatures.Components;

partial class CreaturePhysicMaterial
{
private static readonly PhysicMaterial _frictionless = new()
{
dynamicFriction = 0,
staticFriction = 0,
frictionCombine = PhysicMaterialCombine.Multiply,
bounceCombine = PhysicMaterialCombine.Multiply,
};
private void Awake()
{
if (!physicMaterial) physicMaterial = ECCLibrary.ECCUtility.FrictionlessPhysicMaterial;
if (!physicMaterial) physicMaterial = _frictionless;

foreach (Collider componentsInChild in GetComponentsInChildren<Collider>(true))
componentsInChild.sharedMaterial = physicMaterial;
Expand Down
10 changes: 7 additions & 3 deletions SCHIZO/Creatures/Data/ModdedWaterParkCreatureData.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using ECCLibrary.Data;
using Nautilus.Extensions;
using UnityEngine;

namespace SCHIZO.Creatures.Data;
Expand All @@ -14,8 +14,12 @@ public WaterParkCreatureData GetData()
data.daysToGrow = daysToGrow;
data.isPickupableOutside = isPickupableOutside;
data.canBreed = canBreed;
data.eggOrChildPrefab = !string.IsNullOrWhiteSpace(eggOrChild.GetClassID()) ? new CustomGameObjectReference(eggOrChild.GetClassID()) : null;
data.adultPrefab = !string.IsNullOrWhiteSpace(adult.GetClassID()) ? new CustomGameObjectReference(adult.GetClassID()) : null;
string eggId = eggOrChild?.GetClassID();
string adultId = adult?.GetClassID();
data.eggOrChildPrefab = string.IsNullOrEmpty(eggId) ? null : new(eggId);
data.eggOrChildPrefab?.ForceValid();
data.adultPrefab = string.IsNullOrEmpty(adultId) ? null : new(adultId);
data.adultPrefab?.ForceValid();

return data;
}
Expand Down
18 changes: 9 additions & 9 deletions SCHIZO/Creatures/UnityCreaturePrefab.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Diagnostics.CodeAnalysis;
using ECCLibrary;
using Nautilus.Handlers;
using SCHIZO.Helpers;
using SCHIZO.Items;
using UnityEngine;
using OurCreatureData = SCHIZO.Creatures.Data.CreatureData;
Expand All @@ -22,10 +22,10 @@ protected override void SetItemProperties()
{
base.SetItemProperties();

CreatureDataUtils.SetBehaviorType(ModItem, UnityData.BehaviourType);
CreatureData.behaviourTypeList[ModItem] = UnityData.BehaviourType;

if (UnityData.acidImmune) CreatureDataUtils.SetAcidImmune(ModItem);
if (UnityData.bioReactorCharge > 0) CreatureDataUtils.SetBioreactorCharge(ModItem, UnityData.bioReactorCharge);
if (UnityData.acidImmune) DamageSystem.acidImmune = [.. DamageSystem.acidImmune, ModItem];
if (UnityData.bioReactorCharge > 0) BaseBioReactor.charge[ModItem] = UnityData.bioReactorCharge;

if (UnityData.isPickupable)
{
Expand All @@ -42,22 +42,22 @@ protected override void SetupComponents(GameObject instance)
CreatureDeath creatureDeath = instance.GetComponent<CreatureDeath>();
if (creatureDeath)
{
creatureDeath.respawnerPrefab = ObjectReferences.respawnerPrefab;
creatureDeath.respawnerPrefab = ObjectReferences.RespawnerPrefab;
}

SoundOnDamage soundOnDamage = instance.GetComponent<SoundOnDamage>();
if (soundOnDamage)
{
if (soundOnDamage.damageType == DamageType.Collide) soundOnDamage.sound = ECCSoundAssets.FishSplat;
if (soundOnDamage.damageType == DamageType.Collide) soundOnDamage.sound = FMODHelpers.GameEvents.FishSplat;
else LOGGER.LogWarning($"Creature {PrefabInfo.ClassID} has SoundOnDamage component with damage type {soundOnDamage.damageType} which is not supported");
}

LiveMixin liveMixin = instance.GetComponent<LiveMixin>();
if (liveMixin && liveMixin.data)
{
liveMixin.data.damageEffect = ObjectReferences.genericCreatureHit;
liveMixin.data.deathEffect = ObjectReferences.genericCreatureHit;
liveMixin.data.electricalDamageEffect = ObjectReferences.electrocutedEffect;
liveMixin.data.damageEffect = ObjectReferences.GenericCreatureHit;
liveMixin.data.deathEffect = ObjectReferences.GenericCreatureHit;
liveMixin.data.electricalDamageEffect = ObjectReferences.ElectrocutedEffect;
}

if (UnityData.waterParkData)
Expand Down
14 changes: 14 additions & 0 deletions SCHIZO/Helpers/FMODHelpers.GameEvents.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SCHIZO.Helpers;
partial class FMODHelpers
{
public static class GameEvents
{
public static FMODAsset FishSplat { get; } = GetFmodAsset("event:/sub/common/fishsplat");
}
}
83 changes: 72 additions & 11 deletions SCHIZO/Helpers/FMODHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using FMOD;
using FMOD.Studio;
using FMODUnity;
Expand All @@ -8,7 +9,7 @@
using STOP_MODE = FMOD.Studio.STOP_MODE;

namespace SCHIZO.Helpers;
internal static class FMODHelpers
internal static partial class FMODHelpers
{
/// <summary>
/// Attempts to load an FMOD bank from embedded resources.
Expand Down Expand Up @@ -53,28 +54,38 @@ public static void LoadSubBank(string name, bool throwOnFail = false)
{
LoadBankFromResources($"{name}.bank", throwOnFail);
}
// TODO this can fail if the path/id aren't found but i cba to write the Try___ methods right now

// TODO these can fail if the path/id aren't found but i cba to write the Try___ methods right now
public static string GetPath(string guid)
{
if (!Guid.TryParse(guid, out Guid guid_)) return null;

RuntimeManager.StudioSystem.lookupPath(guid_, out string pathFromId).CheckResult();
return GetPath(guid_);
}
public static string GetPath(Guid guid)
{
RuntimeManager.StudioSystem.lookupPath(guid, out string pathFromId).CheckResult();
return pathFromId;
}
public static string GetId(string path)
{
if (string.IsNullOrEmpty(path)) return null;
Guid guid = GetGuid(path);
return guid == default ? null : guid.ToString();
}
public static Guid GetGuid(string path)
{
if (string.IsNullOrEmpty(path)) return default;

RuntimeManager.StudioSystem.lookupID(path, out Guid guidFromPath).CheckResult();
return guidFromPath == default ? null : guidFromPath.ToString();
RuntimeManager.StudioSystem.lookupID(path, out Guid guid).CheckResult();
return guid;
}

public static void PlayId(this FMOD_CustomEmitter emitter, string id, bool is3d = true)
=> PlayFmod(emitter, GetPath(id), id, is3d);
public static void PlayGuid(this FMOD_CustomEmitter emitter, Guid guid, bool is3d = true)
=> PlayFmod(emitter, GetPath(guid), guid, is3d);
public static void PlayPath(this FMOD_CustomEmitter emitter, string path, bool is3d = true)
=> PlayFmod(emitter, path, GetId(path), is3d);
=> PlayFmod(emitter, path, GetGuid(path), is3d);

public static void PlayFmod(this FMOD_CustomEmitter emitter, string path, string id, bool is3d, float delay = 0)
public static void PlayFmod(this FMOD_CustomEmitter emitter, string path, Guid guid, bool is3d, float delay = 0)
{
if (string.IsNullOrEmpty(path)) return;

Expand All @@ -84,7 +95,7 @@ public static void PlayFmod(this FMOD_CustomEmitter emitter, string path, string
return;
}

emitter.SetAsset(AudioUtils.GetFmodAsset(path, id));
emitter.SetAsset(GetFmodAsset(path, guid));
emitter.SetParameterValue("3D", is3d ? 1 : 0);
emitter.SetParameterValue("Delay", delay);

Expand Down Expand Up @@ -156,4 +167,54 @@ public static EventInstance PlayOneShotAttached(Guid guid, GameObject gameObject
evt.release();
return evt;
}

private static Dictionary<Guid, FMODAsset> _fmodAssetPool = [];
public static FMODAsset GetFmodAsset(string path)
{
if (string.IsNullOrEmpty(path)) return null;

Guid guid = GetGuid(path);
if (guid == default)
{
LOGGER.LogWarning($"Tried to get FMODAsset for unknown path \"{path}\"");
return null;
}
return GetFmodAssetNoCheck(path, guid);
}
public static FMODAsset GetFmodAsset(Guid guid)
{
if (guid == default) return null;
string path = GetPath(guid);

if (path is null)
{
LOGGER.LogWarning($"Tried to get FMODAsset for unknown guid {guid}");
return null;
}

return GetFmodAssetNoCheck(path, guid);
}
public static FMODAsset GetFmodAsset(string path, Guid guid)
{
if (string.IsNullOrEmpty(path)) return null;

if (guid != GetGuid(path))
{
LOGGER.LogWarning($"Tried to get FMODAsset for path \"{path}\" and guid {guid} which don't match!");
return null;
}
return GetFmodAssetNoCheck(path, guid);
}

private static FMODAsset GetFmodAssetNoCheck(string path, Guid guid)
{
if (_fmodAssetPool.TryGetValue(guid, out FMODAsset asset) && asset)
return asset;

asset = ScriptableObject.CreateInstance<FMODAsset>();
asset.path = path;
asset.id = guid.ToString();
_fmodAssetPool[guid] = asset;
return asset;
}
}
Loading

0 comments on commit a45e946

Please sign in to comment.