Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Biome Handler #511

Merged
merged 19 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add BiomeHandler
  • Loading branch information
LeeTwentyThree committed Dec 18, 2023
commit 727abbfaf95ecbe51f1339234270469b6781fe9a
112 changes: 112 additions & 0 deletions Nautilus/Handlers/BiomeHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using Nautilus.Patchers;
using Nautilus.Utility;
using UnityEngine;

namespace Nautilus.Handlers;

/// <summary>
/// A handler class for registering new biome types.
/// </summary>
public static class BiomeHandler
{
/// <summary>
/// Registers a new biome type into the game.
/// </summary>
/// <param name="name">The name of the biome, as seen in the F1 menu.</param>
/// <param name="settings">The fog settings of the biome. See <see cref="CreateBiomeSettings"/>.</param>
/// <param name="sky">The Sky of the biome, which determines reflections and general lighting.</param>
public static void RegisterBiome(string name, WaterscapeVolume.Settings settings, SkyReference sky)
{
BiomePatcher.RegisterBiome(new BiomePatcher.CustomBiomeData(name, settings, sky));
}

/// <summary>
/// <para>A shorthand for creating an instance of the <see cref="WaterscapeVolume.Settings"/> class.</para>
/// <para>A list of base game values can be found on this page: https://subnauticamodding.github.io/Nautilus/tutorials/biomes.html</para>
/// </summary>
/// <param name="absorption">Attenuation coefficients of light (1/cm), red green and blue respectively. The default value is 100f, 18.29155f, 3.531373f.</param>
/// <param name="scattering">The strength of light scattering, 1f by default.</param>
/// <param name="scatteringColor">The color of light scattering. Default value is white.</param>
/// <param name="murkiness">The murkiness of the water. Default value is 1f, recommended range is 0f-20f.</param>
/// <param name="emissive">The emission color of the fog. Default value is black.</param>
/// <param name="emissiveScale">The emission strength of the fog. Default value is 1f.</param>
/// <param name="startDistance">The starting distance of the fog. Default value is 25f. Don't make this too high.</param>
/// <param name="sunlightScale">The strength of sunlight in this biome. Default value is 1f.</param>
/// <param name="ambientScale">The strength of ambient light in this biome. Default value is 1f.</param>
/// <param name="temperature">The temperature of this biome in Celsius. Default value is 24f.</param>
/// <returns>An instance of the class with all settings applied.</returns>
public static WaterscapeVolume.Settings CreateBiomeSettings(Vector3 absorption, float scattering,
Color scatteringColor, float murkiness, Color emissive, float emissiveScale = 1, float startDistance = 25,
float sunlightScale = 1, float ambientScale = 1, float temperature = 24)
{
return new WaterscapeVolume.Settings()
{
absorption = absorption,
scattering = scattering,
scatteringColor = scatteringColor,
murkiness = murkiness,
emissive = emissive,
emissiveScale = emissiveScale,
startDistance = startDistance,
sunlightScale = sunlightScale,
ambientScale = ambientScale,
temperature = temperature
};
}

/// <summary>
/// Defines a reference to a new or existing Sky prefab.
/// </summary>
public class SkyReference
{
private enum Type
{
GameObjectReference,
StringLookup
}

private readonly GameObject _obj;
private readonly string _existingSkyPrefabNameToLookUp;
private readonly Type _type;

/// <summary>
/// Defines a reference to a new or existing Sky prefab.
/// </summary>
/// <param name="obj"></param>
public SkyReference(GameObject obj)
{
_obj = obj;
_type = Type.GameObjectReference;
}

/// <summary>
/// Defines a reference to a base-game Sky prefab.
/// </summary>
/// <param name="existingSkyPrefabName"><para>The name of the Sky prefab from the list of base-game Skies, i.e. "SkySafeShallows".</para>
/// <para>A list of valid inputs can be found on this page: https://subnauticamodding.github.io/Nautilus/tutorials/biomes.html</para></param>
public SkyReference(string existingSkyPrefabName)
{
_existingSkyPrefabNameToLookUp = existingSkyPrefabName;
_type = Type.StringLookup;
}

public virtual GameObject GetSkyPrefabAtRuntime(WaterBiomeManager waterBiomeManager)
{
if (_type == Type.StringLookup)
{
foreach (var settings in waterBiomeManager.biomeSettings)
{
if (settings.skyPrefab.name == _existingSkyPrefabNameToLookUp)
{
return settings.skyPrefab;
}
}

InternalLogger.Error($"No existing Sky prefab found by name '{_existingSkyPrefabNameToLookUp}'");
return null;
}

return _obj;
}
}
}
2 changes: 2 additions & 0 deletions Nautilus/Initializer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using BepInEx;
using HarmonyLib;
using Nautilus.Handlers;
using Nautilus.Patchers;
using Nautilus.Utility;
using Nautilus.Utility.ModMessages;
Expand Down Expand Up @@ -77,5 +78,6 @@ static Initializer()
InventoryPatcher.Patch(_harmony);
WaterParkPatcher.Patch(_harmony);
ModMessageSystem.Patch();
BiomePatcher.Patch(_harmony);
}
}
76 changes: 76 additions & 0 deletions Nautilus/Patchers/BiomePatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System.Collections.Generic;
using HarmonyLib;
using mset;
using Nautilus.Handlers;
using UnityEngine;

namespace Nautilus.Patchers;

internal static class BiomePatcher
{
private static readonly List<CustomBiomeData> CustomBiomes = new();

internal static void Patch(Harmony harmony)
{
harmony.PatchAll(typeof(BiomePatcher));
}

internal static void RegisterBiome(CustomBiomeData biome)
{
CustomBiomes.Add(biome);

var manager = WaterBiomeManager.main;
if (manager != null)
{
AddBiomeToWaterBiomeManager(manager, biome);
}
}

[HarmonyPatch(typeof(WaterBiomeManager), nameof(WaterBiomeManager.Start))]
[HarmonyPostfix]
internal static void WaterBiomeManagerStartPostfix(WaterBiomeManager __instance)
{
foreach (var customBiome in CustomBiomes)
{
AddBiomeToWaterBiomeManager(__instance, customBiome);
}
}

internal static void AddBiomeToWaterBiomeManager(WaterBiomeManager manager, CustomBiomeData biome)
{
var skyPrefab = biome.Sky.GetSkyPrefabAtRuntime(manager);
manager.biomeSettings.Add(new WaterBiomeManager.BiomeSettings(){ name = biome.Name, settings = biome.Settings, skyPrefab = skyPrefab});
var newIndexInBiomeLookup = manager.biomeLookup.Count;
Sky biomeSky = null;
if (skyPrefab != null && MarmoSkies.main != null)
{
biomeSky = MarmoSkies.main.GetSky(skyPrefab);
}
manager.biomeSkies.Add(biomeSky);
if (manager.biomeLookup.ContainsKey(biome.Name))
{
Debug.LogWarningFormat("WaterBiomeManager: biomeSettings contains multiple instances of the same biome name: {0}", new object[]
{
biome.Name
});
}
else
{
manager.biomeLookup.Add(biome.Name, newIndexInBiomeLookup);
}
}

internal class CustomBiomeData
{
public string Name { get; }
public WaterscapeVolume.Settings Settings { get; }
public BiomeHandler.SkyReference Sky { get; }

public CustomBiomeData(string name, WaterscapeVolume.Settings settings, BiomeHandler.SkyReference sky)
{
Name = name;
Settings = settings;
Sky = sky;
}
}
}