Closed sp00ktober closed 1 year ago
[HarmonyPatch(typeof(EntityVisualizers))]
internal class EntityVisualizers_Patch
{
[HarmonyPrefix]
[HarmonyPatch(typeof(EntityVisualizers), "UpdateActivation")]
public static void UpdateActivation_Prefix(EntityVisualizers __instance, MonoBehaviour visualizer )
{
if(visualizer.GetType() == typeof(ToolBehaviour))
{
// reflection hell and very broken code incomming but it might make the inventory work
// however this is brute force and we should find out how the game usually does this
System.Type tConnectionHandle = AccessTools.TypeByName("ConnectionHandle");
System.Type tConnection = AccessTools.TypeByName("Connection");
ToolState.Impl impl1 = new ToolState.Impl((Improbable.Worker.Connection)AccessTools.Constructor(tConnection, new System.Type[] { tConnectionHandle }).Invoke(new object[] { AccessTools.Constructor(tConnectionHandle).Invoke(new object[] { }) }), new EntityId(0), new ToolState.Data(3));
ToolRequestState.Impl impl2 = new ToolRequestState.Impl((Improbable.Worker.Connection)AccessTools.Constructor(tConnection, new System.Type[] { tConnectionHandle }).Invoke(new object[] { AccessTools.Constructor(tConnectionHandle).Invoke(new object[] { }) }), new EntityId(0), new ToolRequestState.Data());
IMemberAdapter impl1FieldInfo = VisualizerMetadataLookup.Instance.GetFieldInfo(impl1.GetType(), visualizer.GetType());
IMemberAdapter impl2FieldInfo = VisualizerMetadataLookup.Instance.GetFieldInfo(impl2.GetType(), visualizer.GetType());
if(impl1FieldInfo != null && impl2FieldInfo != null)
{
AccessTools.Method(typeof(EntityVisualizers), "InjectField").Invoke(__instance, new object[] { visualizer, impl1FieldInfo, impl1});
AccessTools.Method(typeof(EntityVisualizers), "InjectField").Invoke(__instance, new object[] { visualizer, impl2FieldInfo, impl2 });
}
}
}
}
This patch fixes the above error message by getting past the below check (this.AllFieldReadersAndWritersInjected(visualizer)
) which enables the ToolBehaviour
on the player and calls its OnEnable()
method (which is what fixes the above error):
private void UpdateActivation(MonoBehaviour visualizer)
{
if (this.IsMarkedAsDisabled(visualizer))
{
this.Deactivate(visualizer);
}
else if (VisualizerMetadataLookup.Instance.AreAllRequiredFieldsInjectable(visualizer.GetType()) && this.AllFieldReadersAndWritersInjected(visualizer))
{
this.Activate(visualizer);
}
}
However this is not the way to go, its only for testing. The game still throws errors later when trying to open the inventory but also just by loading into the game, see below.
NullReferenceException: Object reference not set to an instance of an object
at Travellers.UI.PlayerInventory.HotBarScreen.RefreshHotbarSlots () [0x00000] in <filename unknown>:0
at Travellers.UI.PlayerInventory.HotBarScreen.ProtectedInit () [0x00000] in <filename unknown>:0
at Travellers.UI.Framework.UIMonoLifetimeController.Initialise () [0x00000] in <filename unknown>:0
at Travellers.UI.Framework.UIObjectFactory.Create[HotBarScreen] (UIElementType elementType, UIFillType fillType, UnityEngine.Transform parent, Boolean isObjectActive, System.String prefabName) [0x00000] in <filename unknown>:0
UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
UnityEngine.Logger:LogException(Exception, Object)
UnityEngine.Debug:LogException(Exception)
WAUnityLogger:LogToLocal(WALogLevel, Object, String, String, Dictionary`2, Exception, String)
WAUnityLogger:Log(WALogLevel, Object, String, String, Dictionary`2, Exception)
WAUtilities.Logging.WALogger:Exception(Exception, Dictionary`2)
Travellers.UI.Framework.UIErrorHandler:TriggerExceptionHandler(String, Exception, Action, Action)
Travellers.UI.Framework.UIObjectFactory:Create(UIElementType, UIFillType, Transform, Boolean, String)
Travellers.UI.Framework.HUDState:CreateScreens(Dictionary`2)
Travellers.UI.Framework.WindowState:EnterState()
Travellers.UI.Framework.DissociatedStatesStack:PushState(WindowState)
Travellers.UI.Framework.UIWindowController:PushState(WindowState)
GameStateMachine.InGameState:OnEnterState()
FSM.<SwitchStateWithLoading>c__AnonStorey0:<>m__5(IState)
RSG.<>c__DisplayClass20:<Then>b__1e(IState)
RSG.Promise`1:InvokeHandler(Action`1, IRejectable, IState)
RSG.Promise`1:ActionHandlers(IRejectable, Action`1, Action`1)
RSG.Promise`1:Then(Action`1, Action`1)
RSG.Promise`1:Then(Action`1)
FSM.StateMachine:SwitchStateWithLoading(IState)
FSM.StateMachine:SwitchState(IState)
FSM.StateMachine:ProcessState(IState)
FSM.StateMachine:Update(Single)
GameStateMachine.Bootstrap:Update()
[2023-01-23T23:23:15]..[EXCEPTION] [DEFAULT] [Exception] Object reference not set to an instance of an object
exception=System.NullReferenceException: Object reference not set to an instance of an object
at LorePiecesCollectorVisualizer.GetKnownPieces () [0x00000] in <filename unknown>:0
at LoreUI.RefreshLore (Boolean refreshSelected) [0x00000] in <filename unknown>:0
at LoreUI.Init () [0x00000] in <filename unknown>:0
at Travellers.UI.PlayerInventory.LogbookUI.ProtectedInit () [0x00000] in <filename unknown>:0
at Travellers.UI.Framework.UIMonoLifetimeController.Initialise () [0x00000] in <filename unknown>:0
at Travellers.UI.Framework.UIObjectFactory.Create[LogbookUI] (UIElementType elementType, UIFillType fillType, UnityEngine.Transform parent, Boolean isObjectActive, System.String prefabName) [0x00000] in <filename unknown>:0
at LorePiecesCollectorVisualizer.GetKnownPieces () [0x00000] in <filename unknown>:0
at LoreUI.RefreshLore (Boolean refreshSelected) [0x00000] in <filename unknown>:0
at LoreUI.Init () [0x00000] in <filename unknown>:0
at Travellers.UI.PlayerInventory.LogbookUI.ProtectedInit () [0x00000] in <filename unknown>:0
at Travellers.UI.Framework.UIMonoLifetimeController.Initialise () [0x00000] in <filename unknown>:0
at Travellers.UI.Framework.UIObjectFactory.Create[LogbookUI] (UIElementType elementType, UIFillType fillType, UnityEngine.Transform parent, Boolean isObjectActive, System.String prefabName) [0x00000] in <filename unknown>:0
NullReferenceException: Object reference not set to an instance of an object
at LorePiecesCollectorVisualizer.GetKnownPieces () [0x00000] in <filename unknown>:0
at LoreUI.RefreshLore (Boolean refreshSelected) [0x00000] in <filename unknown>:0
at LoreUI.Init () [0x00000] in <filename unknown>:0
at Travellers.UI.PlayerInventory.LogbookUI.ProtectedInit () [0x00000] in <filename unknown>:0
at Travellers.UI.Framework.UIMonoLifetimeController.Initialise () [0x00000] in <filename unknown>:0
at Travellers.UI.Framework.UIObjectFactory.Create[LogbookUI] (UIElementType elementType, UIFillType fillType, UnityEngine.Transform parent, Boolean isObjectActive, System.String prefabName) [0x00000] in <filename unknown>:0
UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
UnityEngine.Logger:LogException(Exception, Object)
UnityEngine.Debug:LogException(Exception)
WAUnityLogger:LogToLocal(WALogLevel, Object, String, String, Dictionary`2, Exception, String)
WAUnityLogger:Log(WALogLevel, Object, String, String, Dictionary`2, Exception)
WAUtilities.Logging.WALogger:Exception(Exception, Dictionary`2)
Travellers.UI.Framework.UIErrorHandler:TriggerExceptionHandler(String, Exception, Action, Action)
Travellers.UI.Framework.UIObjectFactory:Create(UIElementType, UIFillType, Transform, Boolean, String)
Travellers.UI.PlayerInventory.LogbookModule:CreateMainComponent(Transform)
Travellers.UI.PlayerInventory.BaseSheetModule:.ctor(Transform, Transform, Action`1, UIToggleGroup)
Travellers.UI.PlayerInventory.CharacterSheetModule:.ctor(Transform, Transform, HorizontalOrVerticalLayoutGroup, Action`1, UIToggleGroup)
Travellers.UI.PlayerInventory.LogbookModule:.ctor(Transform, Transform, HorizontalOrVerticalLayoutGroup, Action`1, UIToggleGroup)
Travellers.UI.PlayerInventory.CharacterSheetScreen:ProtectedInit()
Travellers.UI.Framework.UIMonoLifetimeController:Initialise()
Travellers.UI.Framework.UIObjectFactory:Create(UIElementType, UIFillType, Transform, Boolean, String)
Travellers.UI.Framework.HUDState:CreateScreens(Dictionary`2)
Travellers.UI.Framework.WindowState:EnterState()
Travellers.UI.Framework.DissociatedStatesStack:PushState(WindowState)
Travellers.UI.Framework.UIWindowController:PushState(WindowState)
GameStateMachine.InGameState:OnEnterState()
FSM.<SwitchStateWithLoading>c__AnonStorey0:<>m__5(IState)
RSG.<>c__DisplayClass20:<Then>b__1e(IState)
RSG.Promise`1:InvokeHandler(Action`1, IRejectable, IState)
RSG.Promise`1:ActionHandlers(IRejectable, Action`1, Action`1)
RSG.Promise`1:Then(Action`1, Action`1)
RSG.Promise`1:Then(Action`1)
FSM.StateMachine:SwitchStateWithLoading(IState)
FSM.StateMachine:SwitchState(IState)
FSM.StateMachine:ProcessState(IState)
FSM.StateMachine:Update(Single)
GameStateMachine.Bootstrap:Update()