lloesche / valheim-server-docker

Valheim dedicated gameserver with automatic update, World backup, BepInEx and ValheimPlus mod support
https://hub.docker.com/r/lloesche/valheim-server
Apache License 2.0
1.91k stars 269 forks source link

Mods that install translation yml files can conflict due to the symbolic link hierarchy of /config/bepinex/ to /opt/data/bepinex/BepInEx/ #614

Open gdragon-git opened 1 year ago

gdragon-git commented 1 year ago

The symbolic link that the game uses for runtime to link back to the config folder is catching the plugins folder and yml files that were already loaded once, I'm assuming.

Repro: Add these mods to a clean install: OdinPlus-CrystalLights OdinPlus-OdinsKingdom OdinPlus-OdinsSteelworks Smoothbrain-Jewelcrafting

The OdinPlus mods each have a [modname].English.yml file in their respective directories: CrystalLights.English.yml OdinsKingdom.English.yml OdinsSteelworks.English.yml

It appears that because the way this docker has a symbolic link to the config folder which has the plugins folder used for pre-deployment to /opt/data, there is a circular issue happening where the yml files for the mods get read twice. This cause multiple errors, and in this case, a strange null reference exception, too.

[Warning: Unity Log] Duplicate key English found for OdinsKingdom. The duplicate file found at /opt/valheim/bepinex/BepInEx/plugins/OdinPlus-OdinsKingdom/OdinsKingdom.English.yml will be skipped. [Info : Unity Log] 04/02/2023 10:36:50: Loaded localization file #0 - 'localization' language: 'English'

[Warning: Unity Log] Duplicate key English found for OdinsKingdom. The duplicate file found at /opt/valheim/bepinex/BepInEx/plugins/OdinPlus-OdinsKingdom/OdinsKingdom.English.yml will be skipped. [Info : Unity Log] 04/02/2023 10:36:51: Loaded localization file #1 - 'localization_extra' language: 'English'

[Info : BepInEx] Loading [CrystalLights 1.0.7] [Error : Unity Log] ArgumentException: An item with the same key has already been added. Key: English Stack trace: System.Collections.Generic.Dictionary2[TKey,TValue].TryInsert (TKey key, TValue value, System.Collections.Generic.InsertionBehavior behavior) (at <695d1cc93cca45069c528c15c9fdd749>:0) System.Collections.Generic.Dictionary2[TKey,TValue].Add (TKey key, TValue value) (at <695d1cc93cca45069c528c15c9fdd749>:0) System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] keySelector, System.Func2[T,TResult] elementSelector, System.Collections.Generic.IEqualityComparer1[T] comparer) (at <351e49e2a5bf4fd6beabb458ce2255f3>:0) System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] keySelector, System.Func`2[T,TResult] elementSelector) (at <351e49e2a5bf4fd6beabb458ce2255f3>:0) LocalizationManager.Localizer.LoadLocalization (Localization __instance, System.String language) (at <9f80e7b068584aef864ca3f29a29214a>:0) LocalizationManager.Localizer.Load () (at <9f80e7b068584aef864ca3f29a29214a>:0) CrystalLights.CrystalLights.Awake () (at <9f80e7b068584aef864ca3f29a29214a>:0) UnityEngine.GameObject:AddComponent(Type) BepInEx.Bootstrap.Chainloader:Start() UnityEngine.UI.Image:OnCanvasHierarchyChanged()

[Info : BepInEx] Loading [OdinsSteelworks 0.1.12] [Error : Unity Log] ArgumentException: An item with the same key has already been added. Key: English Stack trace: System.Collections.Generic.Dictionary2[TKey,TValue].TryInsert (TKey key, TValue value, System.Collections.Generic.InsertionBehavior behavior) (at <695d1cc93cca45069c528c15c9fdd749>:0) System.Collections.Generic.Dictionary2[TKey,TValue].Add (TKey key, TValue value) (at <695d1cc93cca45069c528c15c9fdd749>:0) System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] keySelector, System.Func2[T,TResult] elementSelector, System.Collections.Generic.IEqualityComparer1[T] comparer) (at <351e49e2a5bf4fd6beabb458ce2255f3>:0) System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] keySelector, System.Func`2[T,TResult] elementSelector) (at <351e49e2a5bf4fd6beabb458ce2255f3>:0) LocalizationManager.Localizer.LoadLocalization (Localization __instance, System.String language) (at :0) LocalizationManager.Localizer.Load () (at :0) OdinsSteelworks.OdinsSteelworks.Awake () (at :0) UnityEngine.GameObject:AddComponent(Type) BepInEx.Bootstrap.Chainloader:Start() UnityEngine.UI.Image:OnCanvasHierarchyChanged()

Eventually it causes [Error : Unity Log] The WorldGenerator instance was null which then leads to a massive spam of [Error : Unity Log] NullReferenceException: Object reference not set to an instance of an object Stack trace: ZInput.GetButtonDown (System.String name) (at <19a546e6f6564ae49c59d4e69bf4c6f6>:0) UIGamePad.ButtonPressed () (at <835a3a371c5a46df97eae1200aa13dbc>:0) UIGamePad.Update () (at <835a3a371c5a46df97eae1200aa13dbc>:0)

Other mods that may encounter this problem in this docker because of their use of translation files in the same naming format are: AzuAntiCheat (AzuAnticheat.English.yml) and blacks7ar.TeleportationMeads (TeleportationMeads.English.yml)

The OdinPlus team suggest deleting the translation yml for their mods on the dedicated server as a workaround. However, they could not guarantee that a server side mod might not need a translation yml for other purposes, so I wanted to raise this issue to you, @lloesche .

Full log here LogOutput.log

https://justpaste.it/byp2t

gdragon-git commented 1 year ago

What's the reason of having the configuration files in /config/ one level down from the plugins folder? Instead at the same level of the plugins, so when the symbolic link happens in /opt/bepenix, it doesn't have this issue in the future, or others like it where the plugins folder gets read again after already having been copied.