MelonLoader

MelonLoader

554 Downloads

[Bug]: Error / incorrect values when reading Nullable<T> properties

ModsOfPantheon opened this issue ยท 4 comments

commented

All of the following criteria must be met

  • All Requirements must be installed.
  • Changed the title so that it doesn't just says "[Bug]: "
  • I have searched the GitHub issues for my bug, even in the closed issues.

All of the following are optional to answer

  • Tried reinstalling the Game.
  • Tried reinstalling MelonLoader.
  • Tried restarting PC.
  • Was able to see the Start Screen.

Describe the issue.

Trying to read a property that is Nullable<T> will result in an exception if value is null, or an incorrect value if not null.

I would expect to be able to read the property with a null conditional operator like so
MelonLogger.Msg(template.Duration?.value);
But this results in the exception in the logs below if the value is null.

To try to avoid this I can catch the exception

int? duration = null;
try
{
    duration = template.Duration?.value;
}
catch (Exception)
{
    // ignored
}

and this no longer throws, but the value returned is incorrect, in this case -534465616. Calling GetValueOrDefault will return default in these cases.

Full log below

[09:54:08.328] ------------------------------
[09:54:08.360] MelonLoader v0.6.6 Open-Beta
[09:54:08.361] OS: Windows 10
[09:54:08.361] Hash Code: 81E5A4A5974318B4F948B1A58B8459762E3F307B880356782FAB3857F0658A37
[09:54:08.361] ------------------------------
[09:54:08.362] Game Type: Il2cpp
[09:54:08.362] Game Arch: x64
[09:54:08.362] ------------------------------
[09:54:08.362] Command-Line: 
[09:54:08.363] ------------------------------
[09:54:08.363] Core::BasePath = C:\Program Files (x86)\Steam\steamapps\common\Pantheon Rise of the Fallen
[09:54:08.363] Game::BasePath = C:\Program Files (x86)\Steam\steamapps\common\Pantheon Rise of the Fallen
[09:54:08.364] Game::DataPath = C:\Program Files (x86)\Steam\steamapps\common\Pantheon Rise of the Fallen\Pantheon_Data
[09:54:08.364] Game::ApplicationPath = C:\Program Files (x86)\Steam\steamapps\common\Pantheon Rise of the Fallen\Pantheon.exe
[09:54:08.364] Runtime Type: net6
[09:54:08.814] ------------------------------
[09:54:08.815] Game Name: Pantheon
[09:54:08.815] Game Developer: Visionary Realms
[09:54:08.817] Unity Version: 2022.3.51f1
[09:54:08.817] Game Version:    
[09:54:08.817] ------------------------------

[09:54:09.984] Preferences Loaded!

[09:54:09.998] Loading UserLibs from 'C:\Program Files (x86)\Steam\steamapps\common\Pantheon Rise of the Fallen\UserLibs'...

[09:54:10.010] Loading Plugins from 'C:\Program Files (x86)\Steam\steamapps\common\Pantheon Rise of the Fallen\Plugins'...
[09:54:10.012] 0 Plugins loaded.
[09:54:15.420] Loading Il2CppAssemblyGenerator...
[09:54:15.443] [Il2CppAssemblyGenerator] Contacting RemoteAPI...
[09:54:15.633] [Il2CppAssemblyGenerator] Game Not Found on RemoteAPI Host (https://api.melonloader.com/api/v1/game/pantheon)
[09:54:15.633] [Il2CppAssemblyGenerator] RemoteAPI.DumperVersion = null
[09:54:15.634] [Il2CppAssemblyGenerator] RemoteAPI.ObfuscationRegex = null
[09:54:15.634] [Il2CppAssemblyGenerator] RemoteAPI.MappingURL = null
[09:54:15.635] [Il2CppAssemblyGenerator] RemoteAPI.MappingFileSHA512 = null
[09:54:15.641] [Il2CppAssemblyGenerator] Using Cpp2IL Version: 2022.1.0-pre-release.18
[09:54:15.641] [Il2CppAssemblyGenerator] Using Il2CppInterop Version = 1.4.6-ci.579+9d4599dc78d69ede49a2ee96a1ccf41eec02db5b
[09:54:15.641] [Il2CppAssemblyGenerator] Using Unity Dependencies Version = 2022.3.51
[09:54:15.642] [Il2CppAssemblyGenerator] Using Deobfuscation Regex = null
[09:54:15.643] [Il2CppAssemblyGenerator] Cpp2IL is up to date.
[09:54:15.643] [Il2CppAssemblyGenerator] UnityDependencies is up to date.
[09:54:15.643] [Il2CppAssemblyGenerator] Checking GameAssembly...
[09:54:15.869] [Il2CppAssemblyGenerator] Assembly is up to date. No Generation Needed.

[09:54:15.873] Loading Mods from 'C:\Program Files (x86)\Steam\steamapps\common\Pantheon Rise of the Fallen\Mods'...
[09:54:15.895] ------------------------------
[09:54:15.900] Melon Assembly loaded: '.\Mods\Pantheon.dll'
[09:54:15.900] SHA256 Hash: '7E2E439310F4CE0798FDE9803EB63B5830401C91F5A76ED13ED35799B1306FAB'

[09:54:16.361] ------------------------------
[09:54:16.361] Test v1.0.0
[09:54:16.361] by Test
[09:54:16.363] Assembly: Test.dll
[09:54:16.364] ------------------------------
[09:54:16.364] ------------------------------
[09:54:16.365] 1 Mod loaded.

[09:54:17.639] [Il2CppInterop] Class::Init signatures have been exhausted, using a substitute!
[09:54:17.816] [Il2CppInterop] Registered mono type Il2CppInterop.Runtime.DelegateSupport+Il2CppToMonoDelegateReference in il2cpp domain
[09:54:17.903] [Il2CppInterop] Registered mono type MelonLoader.Support.MonoEnumeratorWrapper in il2cpp domain
[09:54:17.963] [Il2CppInterop] Registered mono type MelonLoader.Support.SM_Component in il2cpp domain
[09:54:17.975] Support Module Loaded: C:\Program Files (x86)\Steam\steamapps\common\Pantheon Rise of the Fallen\MelonLoader\Dependencies\SupportModules\Il2Cpp.dll
[09:54:18.355] Mod Initialized!
[09:54:18.584] [Il2CppInterop] Registered mono type Pantheon.OutlineHandler in il2cpp domain
[09:55:39.283] [Test] System.NullReferenceException: Object reference not set to an instance of an object.
   at Il2CppInterop.Runtime.InteropTypes.Il2CppObjectBase.CreateGCHandle(IntPtr objHdl) in /home/runner/work/Il2CppInterop/Il2CppInterop/Il2CppInterop.Runtime/InteropTypes/Il2CppObjectBase.cs:line 50
   at Il2CppInterop.Runtime.InteropTypes.Il2CppObjectBase..ctor(IntPtr pointer) in /home/runner/work/Il2CppInterop/Il2CppInterop/Il2CppInterop.Runtime/InteropTypes/Il2CppObjectBase.cs:line 21
   at Il2CppSystem.Object..ctor(IntPtr pointer)
   at Il2CppSystem.ValueType..ctor(IntPtr pointer)
   at Il2CppSystem.Nullable`1..ctor(IntPtr pointer)
   at Il2Cpp.ItemTemplate.get_Durability()
   at Pantheon.Extensions.ItemTemplateExtensions.ToItemPayload(ItemTemplate template)
   at Pantheon.ModMain.OnUpdate()
   at MelonLoader.MelonEventBase`1.Invoke(Action`1 delegateInvoker) in D:\a\MelonLoader\MelonLoader\MelonLoader\Melons\Events\MelonEvent.cs:line 143

Did you attach your log file?

Yes, I attached my log file to the text box above.

commented

I have a found a workaround, but I don't know if this is expected behaviour. In the case that the property is not null, unboxing to the type gives the correct value. Please let me know if there is a better way to do this.

int? duration = null;
try
{
    duration = template.Duration?.Unbox<int>();
}
catch (Exception)
{
    // ignored
}
commented

If thats a normal nullable, how are you getting an Il2CppInterop exception?

commented

The property in this case is an Il2CppSystem.Nullable:
public unsafe Il2CppSystem.Nullable<int> Duration
Apologies for not making this clear in the issue. Here is the full definition in case it is useful to you:

public unsafe Il2CppSystem.Nullable<int> Duration
{
  [CallerCount(0)] get
  {
	IL2CPP.Il2CppObjectBaseToPtrNotNull((Il2CppObjectBase) this);
	System.IntPtr* numPtr = (System.IntPtr*) null;
	System.IntPtr exc;
	System.IntPtr pointer = IL2CPP.il2cpp_runtime_invoke(ItemTemplate.NativeMethodInfoPtr_get_Duration_Public_get_Nullable_1_Int32_0, IL2CPP.Il2CppObjectBaseToPtrNotNull((Il2CppObjectBase) this), (void**) numPtr, ref exc);
	Il2CppInterop.Runtime.Il2CppException.RaiseExceptionIfNecessary(exc);
	return new Il2CppSystem.Nullable<int>(pointer);
  }
  [CallerCount(0)] set
  {
	IL2CPP.Il2CppObjectBaseToPtrNotNull((Il2CppObjectBase) this);
	System.IntPtr* numPtr = stackalloc System.IntPtr[1]
	{
	  IL2CPP.il2cpp_object_unbox(IL2CPP.Il2CppObjectBaseToPtrNotNull((Il2CppObjectBase) value))
	};
	System.IntPtr exc;
	IL2CPP.il2cpp_runtime_invoke(ItemTemplate.NativeMethodInfoPtr_set_Duration_Public_set_Void_Nullable_1_Int32_0, IL2CPP.Il2CppObjectBaseToPtrNotNull((Il2CppObjectBase) this), (void**) numPtr, ref exc);
	Il2CppInterop.Runtime.Il2CppException.RaiseExceptionIfNecessary(exc);
  }
}
commented

This looks to be a duplicate of an Il2CppInterop issue.
BepInEx/Il2CppInterop#182