Skip to content
This repository has been archived by the owner on Apr 7, 2021. It is now read-only.

Commit

Permalink
fix custom prefabs getting removed on subsequent world loads
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoxiao921 committed Mar 18, 2021
1 parent 11ef224 commit 795344c
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 17 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ Documentation will be included in the *xmldocs*, and further information may be

## Changelog

**0.0.12**

* Custom prefabs now shouldn't be removed on subsequent world loads.
* Added some documentations for mod devs.

**0.0.11**

* Fix nullref for SafeInvoke
Expand Down
14 changes: 2 additions & 12 deletions ValheimLib/ODB/ObjectDBHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ public static class ObjectDBHelper
/// </summary>
public static Action OnAfterInit;

public static void Init()
internal static void Init()
{
On.ObjectDB.Awake += AddCustomData;
On.ZNetScene.Awake += AddCustomPrefabsToZNetSceneDictionary;
On.Player.Load += ReloadKnownRecipes;

SaveCustomData.Init();
Expand All @@ -37,6 +36,7 @@ public static bool Add(CustomItem customItem)
if (customItem.IsValid())
{
CustomItems.Add(customItem);
customItem.ItemPrefab.NetworkRegister();

return true;
}
Expand Down Expand Up @@ -138,16 +138,6 @@ private static void AddCustomData(On.ObjectDB.orig_Awake orig, ObjectDB self)
}
}

private static void AddCustomPrefabsToZNetSceneDictionary(On.ZNetScene.orig_Awake orig, ZNetScene self)
{
orig(self);

foreach (var customItem in CustomItems)
{
self.m_namedPrefabs.Add(customItem.ItemPrefab.name.GetStableHashCode(), customItem.ItemPrefab);
}
}

private static void ReloadKnownRecipes(On.Player.orig_Load orig, Player self, ZPackage pkg)
{
orig(self, pkg);
Expand Down
108 changes: 103 additions & 5 deletions ValheimLib/Prefab.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,28 @@

namespace ValheimLib
{
/// <summary>
/// Helper class for everything Prefab related
/// </summary>
public static class Prefab
{
/// <summary>
/// Name of the Root GameObject that have as childs every Modded GameObject done through InstantiateClone.
/// </summary>
public const string ModdedPrefabsParentName = "ModdedPrefabs";

/// <summary>
/// Prefix used by the Mock System to recognize Mock gameObject that must be replaced at some point.
/// </summary>
public const string MockPrefix = "VLmock_";

internal static List<WeakReference> NetworkedModdedPrefabs = new List<WeakReference>();

private static GameObject _parent;
/// <summary>
/// Parent is the Root GameObject that have as childs every Modded GameObject done through InstantiateClone.
/// Feel free to add your modded prefabs here too
/// </summary>
public static GameObject Parent
{
get
Expand All @@ -30,6 +46,47 @@ public static GameObject Parent
}
}

internal static void Init()
{
On.ZNetScene.Awake += AddCustomPrefabsToZNetSceneDictionary;
}

private static void AddCustomPrefabsToZNetSceneDictionary(On.ZNetScene.orig_Awake orig, ZNetScene self)
{
orig(self);

if (self)
{
foreach (var weakReference in NetworkedModdedPrefabs)
{
if (weakReference.IsAlive)
{
var prefab = (GameObject)weakReference.Target;
if (prefab)
{
self.m_namedPrefabs.Add(prefab.name.GetStableHashCode(), prefab);
}
}
}
}
}

/// <summary>
/// Allow you to register to the ZNetScene list so that its correctly networked by the game.
/// </summary>
/// <param name="prefab">Prefab to register to the ZNetScene list</param>
public static void NetworkRegister(this GameObject prefab)
{
NetworkedModdedPrefabs.Add(new WeakReference(prefab));
}

/// <summary>
/// Allow you to clone a given prefab without modifying the original. Also handle the networking and unique naming.
/// </summary>
/// <param name="gameObject">prefab that you want to clone</param>
/// <param name="nameToSet">name for the new clone</param>
/// <param name="zNetRegister">Must be true if you want to have the prefab correctly networked and handled by the ZDO system. True by default</param>
/// <returns></returns>
public static GameObject InstantiateClone(this GameObject gameObject, string nameToSet, bool zNetRegister = true)
{
const char separator = '_';
Expand All @@ -42,16 +99,18 @@ public static GameObject InstantiateClone(this GameObject gameObject, string nam

if (zNetRegister)
{
var zNetScene = ZNetScene.instance;
if (zNetScene)
{
zNetScene.m_namedPrefabs.Add(prefab.name.GetStableHashCode(), prefab);
}
prefab.NetworkRegister();
}

return prefab;
}

/// <summary>
/// Will try to find the real vanilla prefab from the given mock
/// </summary>
/// <param name="unityObject"></param>
/// <param name="mockObjectType"></param>
/// <returns>the real prefab</returns>
public static UnityObject GetRealPrefabFromMock(UnityObject unityObject, Type mockObjectType)
{
if (unityObject)
Expand All @@ -68,13 +127,23 @@ public static UnityObject GetRealPrefabFromMock(UnityObject unityObject, Type mo
return null;
}

/// <summary>
/// Will try to find the real vanilla prefab from the given mock
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="unityObject"></param>
/// <returns>the real prefab</returns>
public static T GetRealPrefabFromMock<T>(UnityObject unityObject) where T : UnityObject
{
return (T)GetRealPrefabFromMock(unityObject, typeof(T));
}

// Thanks for not using the Resources folder IronGate
// There is probably some oddities in there
/// <summary>
/// Will attempt to fix every field that are mocks gameObjects / Components from the given object.
/// </summary>
/// <param name="objectToFix"></param>
public static void FixReferences(this object objectToFix)
{
var type = objectToFix.GetType();
Expand Down Expand Up @@ -155,6 +224,10 @@ public static void FixReferences(this object objectToFix)
}
}

/// <summary>
/// Fix the components fields of a given gameObject
/// </summary>
/// <param name="gameObject"></param>
public static void FixReferences(this GameObject gameObject)
{
foreach (var component in gameObject.GetComponents<Component>())
Expand All @@ -163,6 +236,11 @@ public static void FixReferences(this GameObject gameObject)
}
}

/// <summary>
/// Will clone all fields from gameObject to objectToClone
/// </summary>
/// <param name="gameObject"></param>
/// <param name="objectToClone"></param>
public static void CloneFields(this GameObject gameObject, GameObject objectToClone)
{
const BindingFlags flags = ReflectionHelper.AllBindingFlags;
Expand Down Expand Up @@ -191,6 +269,9 @@ public static void CloneFields(this GameObject gameObject, GameObject objectToCl
}
}

/// <summary>
/// Helper class for caching gameobjects in the current scene.
/// </summary>
public static class Cache
{
private static readonly Dictionary<Type, Dictionary<string, UnityObject>> DictionaryCache =
Expand All @@ -209,6 +290,12 @@ private static void InitCache(Type type, Dictionary<string, UnityObject> map = n
DictionaryCache[type] = map;
}

/// <summary>
/// Get an instance of an UnityObject from the current scene with the given name
/// </summary>
/// <param name="type"></param>
/// <param name="name"></param>
/// <returns></returns>
public static UnityObject GetPrefab(Type type, string name)
{
if (DictionaryCache.TryGetValue(type, out var map))
Expand All @@ -232,11 +319,22 @@ public static UnityObject GetPrefab(Type type, string name)
return null;
}

/// <summary>
/// Get an instance of an UnityObject from the current scene with the given name
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="name"></param>
/// <returns></returns>
public static T GetPrefab<T>(string name) where T : UnityObject
{
return (T)GetPrefab(typeof(T), name);
}

/// <summary>
/// Get the instances of UnityObjects from the current scene with the given type
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static Dictionary<string, UnityObject> GetPrefabs(Type type)
{
if (DictionaryCache.TryGetValue(type, out var map))
Expand Down
1 change: 1 addition & 0 deletions ValheimLib/ValheimLib.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ private void Awake()
Language.Init();
ODB.ObjectDBHelper.Init();
Spawn.SpawnSystemHelper.Init();
Prefab.Init();

Instance = this;
}
Expand Down

0 comments on commit 795344c

Please sign in to comment.