Refactor LoadLobbyListAndFilterTranspiler
Closed this issue · 0 comments
Right now, the LoadLobbyListAndFilterTranspiler
patch looks like this:
// Does the following:
// - Adds SteamLobbyManager.levelListContainer to the stack
// - Replaces gameObject.GetComponentInChildren<LobbySlot>() with a call to InitializeLobbySlot
// - Calls InitializeLobbySlot(gameObject, levelListContainer), which returns the same component after injecting modded lobby data
// TODO: Directly inject the lobby into InitializeLobbySlot instead of grabbing it in Start() in ModdedLobbySlot
return new CodeMatcher(instructions)
.SearchForward(instruction => instruction.Calls(lobbySlotMethod))
.ThrowIfInvalid("Could not find LobbySlot method")
.RemoveInstructions(1)
.Insert(
new CodeInstruction(OpCodes.Ldloc_1),
new CodeInstruction(OpCodes.Ldfld, levelListContainerField),
new CodeInstruction(
OpCodes.Call,
AccessTools.Method(typeof(LoadLobbyListAndFilterTranspiler), nameof(InitializeLobbySlot))))
.InstructionEnumeration();
// ...
// Inject custom LobbySlot component for modded lobby data
private static LobbySlot InitializeLobbySlot(GameObject gameObject, Transform levelListContainer)
{
var lobbySlot = gameObject.GetComponentInChildren<LobbySlot>();
var moddedLobbySlot = lobbySlot.gameObject.AddComponent<ModdedLobbySlot>();
// Set container parent for hover tooltip position math
moddedLobbySlot.SetParentContainer(levelListContainer.parent);
return lobbySlot;
}
In InitializeLobbySlot
, a new component named ModdedLobbySlot
is added, which uses the following to get a reference to the LobbySlot component:
// Runs after LobbySlot data set
private void Start()
{
// Not 100% ideal, but I don't want to mess with IL/stack weirdness too much right now
_lobbySlot = GetComponent<LobbySlot>();
Waiting until the first frame isn't 100% ideal, as it has to wait to setup the "modded" lobby button, and things could theoretically go wrong. I haven't seen it in practice, but the LobbySlot component could not exist, or it could not be properly initialized by this point.
Ideally, the patch would be moved from replacing gameObject.GetComponentInChildren<LobbySlot>();
, to executing right after the LobbySlot is initialized (around lobbyName = null
).
This way, we could load up the stack with the following info, and create a ModdedLobbySlot instantly.
InitializeLobbySlot(GameObject gameObject, Transform levelListContainer, LobbySlot lobbySlot)
// gameObject to add the component onto
// levelListContainer (ScrollView.Viewport.Content) for later tooltip hover math - stored as SteamLobbyManager.levelListContainer
// LobbySlot to get the lobby info
This probably isn't urgent unless we notice things breaking, but it would improve:
- Compatibility (not sure if anything else replaces
gameObject.GetComponentInChildren<LobbySlot>();
, but still) - Performance (removing a bunch of technically unnecessary GetComponent calls would be nice)
- Reliability (LobbySlot will 100% always exist if we're calling the method)