Added Multilingual Localization

Added Host IP Information Panel

Used 7-bit variant to expand the playersInLobby list and slotId of LobbyMessage

Fixed LAN UI was not displayed after switch save
Fixed where last max player is very difficult to connect
Fixed Join button on the controller is the same as the refresh button
This commit is contained in:
kmyuhkyuk
2026-03-22 16:04:20 +08:00
parent 1a35bc7894
commit 9e7c3ea567
53 changed files with 1514 additions and 164 deletions
@@ -2,7 +2,6 @@
using HarmonyLib;
using MegaCrit.Sts2.addons.mega_text;
using MegaCrit.Sts2.Core.Helpers;
using MegaCrit.Sts2.Core.Localization;
using MegaCrit.Sts2.Core.Multiplayer.Connection;
using MegaCrit.Sts2.Core.Nodes.GodotExtensions;
using MegaCrit.Sts2.Core.Nodes.Screens.MainMenu;
@@ -20,7 +19,6 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
private static void Prefix(NJoinFriendScreen __instance)
{
var lanPanel = new NinePatchRect { Name = "LANPanel" };
__instance.AddChild(lanPanel);
lanPanel.PatchMarginTop = 12;
@@ -66,49 +64,37 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
addressLineEdit.CustomMinimumSize = new Vector2(300, 50);
addressLineEdit.SizeFlagsHorizontal = Control.SizeFlags.ShrinkCenter;
if (__instance.GetNode<NJoinFriendRefreshButton>("RefreshButton").Duplicate() is NJoinFriendRefreshButton
joinButton)
var joinButton = JoinButton.Create(__instance.GetNode<NJoinFriendRefreshButton>("RefreshButton"));
joinButton.Name = "JointButton";
vBoxContainer.AddChild(joinButton);
joinButton.Connect(NClickableControl.SignalName.Released, Callable.From<NClickableControl>(_ =>
{
joinButton.Name = "JointButton";
var addressInfo = addressLineEdit.GetAddressInfo();
vBoxContainer.AddChild(joinButton);
if (!addressInfo.IsValid)
return;
joinButton.CustomMinimumSize = new Vector2(150, 50);
joinButton.SizeFlagsHorizontal = Control.SizeFlags.ShrinkCenter;
SettingsService.Instance.SettingsModel.IPAddress = addressLineEdit.Text;
SettingsService.Instance.WriteSettings();
joinButton.Connect(NClickableControl.SignalName.Released, Callable.From<NClickableControl>(_ =>
ushort port = 33771;
if (addressInfo.Port.HasValue)
{
var addressInfo = addressLineEdit.GetAddressInfo();
port = addressInfo.Port.Value;
}
if (!addressInfo.IsValid)
return;
SettingsService.Instance.SettingsModel.IPAddress = addressLineEdit.Text;
SettingsService.Instance.WriteSettings();
ushort port = 33771;
if (addressInfo.Port.HasValue)
{
port = addressInfo.Port.Value;
}
DisplayServer.WindowSetTitle("Slay The Spire 2 (Client)");
if (addressInfo.Address != null)
{
TaskHelper.RunSafely(
__instance.JoinGameAsync(new ENetClientConnectionInitializer(
SettingsService.Instance.SettingsModel.NetId, addressInfo.Address, port)));
}
}));
joinButton.Material = joinButton.Material.Duplicate() as Material;
Traverse.Create(joinButton).Field("_hsv").SetValue(joinButton.Material);
var joinButtonLabel = joinButton.GetNode<MegaLabel>("Label");
joinButtonLabel.SetTextAutoSize(new LocString("main_menu_ui", "JOIN.title").GetFormattedText());
}
DisplayServer.WindowSetTitle("Slay The Spire 2 (Client)");
if (addressInfo.Address != null)
{
TaskHelper.RunSafely(
__instance.JoinGameAsync(new ENetClientConnectionInitializer(
SettingsService.Instance.SettingsModel.NetId, addressInfo.Address, port)));
}
}));
}
}
}
@@ -1,4 +1,5 @@
using HarmonyLib;
using Godot;
using HarmonyLib;
using MegaCrit.Sts2.Core.Helpers;
using MegaCrit.Sts2.Core.Nodes.Screens.MainMenu;
using SlayTheSpire2.LAN.Multiplayer.Components;
@@ -15,7 +16,7 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
{
if (type == typeof(LanMultiplayerHostSubmenu))
{
if (LanMultiplayerHostSubmenu.Instance == null)
if (!GodotObject.IsInstanceValid(LanMultiplayerHostSubmenu.Instance))
{
var lanMultiplayerHostSubmenu = LanMultiplayerHostSubmenu.Create();
@@ -17,6 +17,13 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
[HarmonyPatch(typeof(NMultiplayerPlayerExpandedState), "_Ready")]
internal class NMultiplayerPlayerExpandedStateReadyPatch
{
[HarmonyReversePatch]
[HarmonyPatch(typeof(NMapDrawings), "GetDrawingStateForPlayer")]
private static object GetDrawingStateForPlayer(NMapDrawings instance, ulong playerId)
{
throw new NotImplementedException();
}
private static void Prefix(NMultiplayerPlayerExpandedState __instance, Player ____player)
{
if (____player.NetId != RunManager.Instance.NetService.NetId)
@@ -48,8 +55,11 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
cardLibraryTickBox.Toggled += tickBox =>
{
var drawingState = Traverse.Create(NMapScreen.Instance?.Drawings)
.Method("GetDrawingStateForPlayer", ____player.NetId).GetValue();
if (NMapScreen.Instance == null)
return;
var drawingState = GetDrawingStateForPlayer(NMapScreen.Instance.Drawings, ____player.NetId);
var drawViewport = Traverse.Create(drawingState).Field("drawViewport").GetValue<SubViewport>();
if (tickBox.IsTicked)
@@ -18,102 +18,101 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
[HarmonyPatch(typeof(NMultiplayerSubmenu), "_Ready")]
internal class NMultiplayerSubmenuReadyPatch
{
[HarmonyReversePatch(HarmonyReversePatchType.Snapshot)]
[HarmonyPatch(typeof(NMultiplayerSubmenu), "UpdateButtons")]
private static void UpdateButtons(NMultiplayerSubmenu instance)
{
throw new NotImplementedException();
}
private static void Prefix(NMultiplayerSubmenu __instance)
{
var buttonContainerNode = __instance.GetNode("ButtonContainer");
if (buttonContainerNode.GetNode("HostButton").Duplicate() is not NSubmenuButton lanHostButton)
return;
if (buttonContainerNode.GetNode("HostButton").Duplicate() is NSubmenuButton lanHostButton)
{
NSubmenuButtonDuplicateMaterial(lanHostButton);
buttonContainerNode.AddChild(lanHostButton);
buttonContainerNode.MoveChild(lanHostButton, 1);
buttonContainerNode.AddChild(lanHostButton);
buttonContainerNode.MoveChild(lanHostButton, 1);
lanHostButton.Connect(NClickableControl.SignalName.Released,
Callable.From<NButton>(_ =>
{
var traverse = Traverse.Create(__instance);
var settingsModel = SettingsService.Instance.SettingsModel;
var stack = traverse.Field("_stack").GetValue<NSubmenuStack>();
if (SaveManager.Instance.Progress.NumberOfRuns > 0)
lanHostButton.Connect(NClickableControl.SignalName.Released,
Callable.From<NButton>(_ =>
{
stack.PushSubmenuType<LanMultiplayerHostSubmenu>();
}
else
var traverse = Traverse.Create(__instance);
var settingsModel = SettingsService.Instance.SettingsModel;
var stack = traverse.Field("_stack").GetValue<NSubmenuStack>();
if (SaveManager.Instance.Progress.NumberOfRuns > 0)
{
stack.PushSubmenuType<LanMultiplayerHostSubmenu>();
}
else
{
LanHostHelper.StartHost(GameMode.Standard,
traverse.Field("_loadingOverlay").GetValue<Control>(), stack, settingsModel.HostPort,
settingsModel.HostMaxPlayers);
}
}));
lanHostButton.SetIconAndLocalization("HOST");
var lanHostTitle = Traverse.Create(lanHostButton).Field("_title").GetValue<MegaLabel>();
lanHostTitle.Text = $"LAN {lanHostTitle.Text}";
LanMultiplayerSubmenuButtonService.Instance.LanHostButton = lanHostButton;
}
if (buttonContainerNode.GetNode("LoadButton").Duplicate() is NSubmenuButton lanLoadButton)
{
NSubmenuButtonDuplicateMaterial(lanLoadButton);
buttonContainerNode.AddChild(lanLoadButton);
buttonContainerNode.MoveChild(lanLoadButton, 2);
lanLoadButton.Connect(NClickableControl.SignalName.Released,
Callable.From<NButton>(_ =>
{
LanHostHelper.StartHost(GameMode.Standard,
traverse.Field("_loadingOverlay").GetValue<Control>(), stack, settingsModel.HostPort,
settingsModel.HostMaxPlayers);
}
}));
lanHostButton.SetIconAndLocalization("HOST");
var lanHostTitle = Traverse.Create(lanHostButton).Field("_title").GetValue<MegaLabel>();
lanHostTitle.Text = $"LAN {lanHostTitle.Text}";
var traverse = Traverse.Create(__instance);
NSubmenuButtonDuplicateMaterial(lanHostButton);
var settingsModel = SettingsService.Instance.SettingsModel;
var lanMultiplayerSubmenuButtonService = LanMultiplayerSubmenuButtonService.Instance;
LanHostHelper.StartLoad(lanLoadButton, traverse.Field("_loadingOverlay").GetValue<Control>(),
traverse.Field("_stack").GetValue<NSubmenuStack>(),
settingsModel.HostPort, settingsModel.HostMaxPlayers);
}));
lanLoadButton.SetIconAndLocalization("MP_LOAD");
var lanLoadButtonTitle = Traverse.Create(lanLoadButton).Field("_title").GetValue<MegaLabel>();
lanLoadButtonTitle.Text = $"LAN {lanLoadButtonTitle.Text}";
lanMultiplayerSubmenuButtonService.LanHostButton = lanHostButton;
LanMultiplayerSubmenuButtonService.Instance.LanLoadButton = lanLoadButton;
}
if (buttonContainerNode.GetNode("LoadButton").Duplicate() is not NSubmenuButton lanLoadButton)
return;
if (buttonContainerNode.GetNode("AbandonButton").Duplicate() is NSubmenuButton lanAbandonButton)
{
NSubmenuButtonDuplicateMaterial(lanAbandonButton);
buttonContainerNode.AddChild(lanLoadButton);
buttonContainerNode.MoveChild(lanLoadButton, 2);
buttonContainerNode.AddChild(lanAbandonButton);
buttonContainerNode.MoveChild(lanAbandonButton, 3);
lanLoadButton.Connect(NClickableControl.SignalName.Released,
Callable.From<NButton>(_ =>
{
var traverse = Traverse.Create(__instance);
lanAbandonButton.Connect(NClickableControl.SignalName.Released,
Callable.From<NButton>(_ =>
{
TaskHelper.RunSafely(
LanHostHelper.TryAbandonMultiplayerRun(() => UpdateButtons(__instance)));
}));
lanAbandonButton.SetIconAndLocalization("MP_ABANDON");
var lanAbandonButtonTitle = Traverse.Create(lanAbandonButton).Field("_title").GetValue<MegaLabel>();
lanAbandonButtonTitle.Text = $"LAN {lanAbandonButtonTitle.Text}";
var settingsModel = SettingsService.Instance.SettingsModel;
LanHostHelper.StartLoad(lanLoadButton, traverse.Field("_loadingOverlay").GetValue<Control>(),
traverse.Field("_stack").GetValue<NSubmenuStack>(),
settingsModel.HostPort, settingsModel.HostMaxPlayers);
}));
lanLoadButton.SetIconAndLocalization("MP_LOAD");
var lanLoadButtonTitle = Traverse.Create(lanLoadButton).Field("_title").GetValue<MegaLabel>();
lanLoadButtonTitle.Text = $"LAN {lanLoadButtonTitle.Text}";
NSubmenuButtonDuplicateMaterial(lanLoadButton);
lanMultiplayerSubmenuButtonService.LanLoadButton = lanLoadButton;
if (buttonContainerNode.GetNode("AbandonButton").Duplicate() is not NSubmenuButton lanAbandonButton)
return;
buttonContainerNode.AddChild(lanAbandonButton);
buttonContainerNode.MoveChild(lanAbandonButton, 3);
lanAbandonButton.Connect(NClickableControl.SignalName.Released,
Callable.From<NButton>(_ =>
{
var traverse = Traverse.Create(__instance);
TaskHelper.RunSafely(
LanHostHelper.TryAbandonMultiplayerRun(() => traverse.Method("UpdateButtons").GetValue()));
}));
lanAbandonButton.SetIconAndLocalization("MP_ABANDON");
var lanAbandonButtonTitle = Traverse.Create(lanAbandonButton).Field("_title").GetValue<MegaLabel>();
lanAbandonButtonTitle.Text = $"LAN {lanAbandonButtonTitle.Text}";
NSubmenuButtonDuplicateMaterial(lanAbandonButton);
lanMultiplayerSubmenuButtonService.LanAbandonButton = lanAbandonButton;
LanMultiplayerSubmenuButtonService.Instance.LanAbandonButton = lanAbandonButton;
}
}
private static void NSubmenuButtonDuplicateMaterial(NSubmenuButton nSubmenuButton)
{
var traverse = Traverse.Create(nSubmenuButton);
var bgPanel = traverse.Field("_bgPanel").GetValue<Control>();
var bgPanel = nSubmenuButton.GetNode<Control>("BgPanel");
bgPanel.Material = bgPanel.Material.Duplicate() as Material;
traverse.Field("_hsv").SetValue(bgPanel.Material);
}
}
@@ -1,5 +1,7 @@
using Godot;
using HarmonyLib;
using MegaCrit.Sts2.addons.mega_text;
using MegaCrit.Sts2.Core.Localization;
using MegaCrit.Sts2.Core.Nodes.Screens.Settings;
using SlayTheSpire2.LAN.Multiplayer.Components;
using SlayTheSpire2.LAN.Multiplayer.Services;
@@ -12,6 +14,13 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
[HarmonyPatch(typeof(NSettingsScreen), "_Ready")]
internal class NSettingsScreenReadyPatch
{
[HarmonyReversePatch]
[HarmonyPatch(typeof(NSettingsPanel), "RefreshSize")]
private static void RefreshSize(NSettingsPanel instance)
{
throw new NotImplementedException();
}
private static void Prefix(NSettingsScreen __instance)
{
var moddingNode = __instance.GetNode("%Modding");
@@ -21,7 +30,7 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
if (__instance.GetNode("%ModdingDivider").Duplicate() is ColorRect hostPortDivider &&
moddingNode.Duplicate() is MarginContainer hostPort &&
hostPort.GetNode("Label") is RichTextLabel hostPortLabel)
hostPort.GetNode("Label") is MegaRichTextLabel hostPortLabel)
{
hostPortDivider.Name = "HostPortDivider";
@@ -40,7 +49,6 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
hostPort.Show();
var hostPortLineEdit = new SpinBox { Name = "HostPortInput" };
hostPort.AddChild(hostPortLineEdit);
hostPortLineEdit.CustomMinimumSize = new Vector2(324, 64);
@@ -62,7 +70,7 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
if (__instance.GetNode("%ModdingDivider").Duplicate() is ColorRect hostMaxPlayersDivider &&
moddingNode.Duplicate() is MarginContainer hostMaxPlayers &&
hostMaxPlayers.GetNode("Label") is RichTextLabel hostMaxPlayersLabel)
hostMaxPlayers.GetNode("Label") is MegaRichTextLabel hostMaxPlayersLabel)
{
hostMaxPlayersDivider.Name = "HostMaxPlayersDivider";
@@ -81,7 +89,6 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
hostMaxPlayers.Show();
var hostMaxPlayersInput = new SpinBox { Name = "HostMaxPlayersInput" };
hostMaxPlayers.AddChild(hostMaxPlayersInput);
hostMaxPlayersInput.CustomMinimumSize = new Vector2(324, 64);
@@ -102,7 +109,7 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
if (__instance.GetNode("%ModdingDivider").Duplicate() is ColorRect playerNameDivider &&
moddingNode.Duplicate() is MarginContainer playerName &&
playerName.GetNode("Label") is RichTextLabel playerNameLabel)
playerName.GetNode("Label") is MegaRichTextLabel playerNameLabel)
{
playerNameDivider.Name = "PlayerNameDivider";
@@ -120,11 +127,15 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
playerName.Show();
var marginContainer = new MarginContainer();
playerName.AddChild(marginContainer);
marginContainer.AddThemeConstantOverride("margin_right", 18);
var playerNameInput = new PlayerNameLineEdit { Name = "PlayerNameInput" };
marginContainer.AddChild(playerNameInput);
playerName.AddChild(playerNameInput);
playerNameInput.CustomMinimumSize = new Vector2(324, 64);
playerNameInput.CustomMinimumSize = new Vector2(308, 64);
playerNameInput.SizeFlagsHorizontal = Control.SizeFlags.ShrinkEnd;
playerNameInput.Alignment = HorizontalAlignment.Center;
@@ -145,7 +156,7 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
if (__instance.GetNode("%ModdingDivider").Duplicate() is ColorRect netIdDivider &&
moddingNode.Duplicate() is MarginContainer netId &&
netId.GetNode("Label") is RichTextLabel netIdLabel)
netId.GetNode("Label") is MegaRichTextLabel netIdLabel)
{
netIdDivider.Name = "NetIDDivider";
@@ -164,7 +175,6 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
netId.Show();
var netIdInput = new SpinBox { Name = "NetIDInput" };
netId.AddChild(netIdInput);
netIdInput.CustomMinimumSize = new Vector2(324, 64);
@@ -186,8 +196,33 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
if (generalSettings is NSettingsPanel nSettingsPanel)
{
Traverse.Create(nSettingsPanel).Method("RefreshSize").GetValue();
RefreshSize(nSettingsPanel);
}
}
}
[HarmonyPatch(typeof(NSettingsScreen), "LocalizeLabels")]
internal class NSettingsScreenLocalizeLabelsPatch
{
[HarmonyReversePatch]
[HarmonyPatch(typeof(NSettingsScreen), "LocHelper")]
private static void LocHelper(Node settingsLineNode, LocString locString)
{
throw new NotImplementedException();
}
private static void Prefix(NSettingsScreen __instance)
{
var content = __instance.GetNode<NSettingsPanel>("%GeneralSettings").Content;
LocHelper(content.GetNode<Node>("HostPort"),
new LocString("settings_ui", "SlayTheSpire2.LAN.Multiplayer.HOST_PORT"));
LocHelper(content.GetNode<Node>("HostMaxPlayers"),
new LocString("settings_ui", "SlayTheSpire2.LAN.Multiplayer.HOST_MAX_PLAYERS"));
LocHelper(content.GetNode<Node>("PlayerName"),
new LocString("settings_ui", "SlayTheSpire2.LAN.Multiplayer.PLAYER_NAME"));
LocHelper(content.GetNode<Node>("NetID"),
new LocString("settings_ui", "SlayTheSpire2.LAN.Multiplayer.NET_ID"));
}
}
}
@@ -5,6 +5,7 @@ using MegaCrit.Sts2.Core.Multiplayer.Game.Lobby;
using MegaCrit.Sts2.Core.Nodes.Screens.CharacterSelect;
using MegaCrit.Sts2.Core.Nodes.Screens.CustomRun;
using MegaCrit.Sts2.Core.Nodes.Screens.DailyRun;
using MegaCrit.Sts2.Core.Nodes.Screens.MainMenu;
using MegaCrit.Sts2.Core.Platform;
using SlayTheSpire2.LAN.Multiplayer.Services;
@@ -14,21 +15,52 @@ using SlayTheSpire2.LAN.Multiplayer.Services;
namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
{
[HarmonyPatch]
internal class RunLoadScreenInitializePatchs
internal class RunLoadScreenInitializeAsHostPatchs
{
private static IEnumerable<MethodInfo> TargetMethods()
{
const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public;
yield return typeof(NMultiplayerLoadGameScreen).GetMethod("InitializeAsHost", flags)!;
yield return typeof(NMultiplayerLoadGameScreen).GetMethod("InitializeAsClient", flags)!;
yield return typeof(NDailyRunLoadScreen).GetMethod("InitializeAsHost", flags)!;
yield return typeof(NDailyRunLoadScreen).GetMethod("InitializeAsClient", flags)!;
yield return typeof(NCustomRunLoadScreen).GetMethod("InitializeAsHost", flags)!;
}
private static void Prefix(NSubmenu __instance, INetGameService gameService)
{
if (gameService.Platform == PlatformType.None)
{
var runScreenService = RunScreenService.Instance;
switch (__instance)
{
case NMultiplayerLoadGameScreen multiplayerLoadGameScreen:
runScreenService.MultiplayerLoadGameScreen = multiplayerLoadGameScreen;
break;
case NDailyRunLoadScreen dailyRunLoadScreen:
runScreenService.DailyRunLoadScreen = dailyRunLoadScreen;
break;
case NCustomRunLoadScreen customRunLoadScreen:
runScreenService.CustomRunLoadScreen = customRunLoadScreen;
break;
}
}
}
}
[HarmonyPatch]
internal class RunLoadScreenInitializeAsClientPatchs
{
private static IEnumerable<MethodInfo> TargetMethods()
{
const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public;
yield return typeof(NMultiplayerLoadGameScreen).GetMethod("InitializeAsClient", flags)!;
yield return typeof(NDailyRunLoadScreen).GetMethod("InitializeAsClient", flags)!;
yield return typeof(NCustomRunLoadScreen).GetMethod("InitializeAsClient", flags)!;
}
private static void Prefix(object __instance, INetGameService gameService)
private static void Prefix(NSubmenu __instance, INetGameService gameService)
{
if (gameService.Platform == PlatformType.None)
{
@@ -4,7 +4,9 @@ using MegaCrit.Sts2.Core.Multiplayer.Game;
using MegaCrit.Sts2.Core.Nodes.Screens.CharacterSelect;
using MegaCrit.Sts2.Core.Nodes.Screens.CustomRun;
using MegaCrit.Sts2.Core.Nodes.Screens.DailyRun;
using MegaCrit.Sts2.Core.Nodes.Screens.MainMenu;
using MegaCrit.Sts2.Core.Platform;
using SlayTheSpire2.LAN.Multiplayer.Components;
using SlayTheSpire2.LAN.Multiplayer.Services;
// ReSharper disable UnusedMember.Global
@@ -13,21 +15,41 @@ using SlayTheSpire2.LAN.Multiplayer.Services;
namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
{
[HarmonyPatch]
internal class RunScreenInitializePatchs
internal class RunScreenReadyPatchs
{
private static IEnumerable<MethodInfo> TargetMethods()
{
const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public;
yield return typeof(NCharacterSelectScreen).GetMethod("_Ready", flags)!;
yield return typeof(NDailyRunScreen).GetMethod("_Ready", flags)!;
yield return typeof(NCustomRunScreen).GetMethod("_Ready", flags)!;
}
private static void Prefix(NSubmenu __instance)
{
var ipAddressInfoPanel = IPAddressInfoPanel.Create();
ipAddressInfoPanel.Name = "IPAddressPanel";
__instance.AddChild(ipAddressInfoPanel);
ipAddressInfoPanel.Visible = false;
}
}
[HarmonyPatch]
internal class RunScreenInitializeAsHostPatchs
{
private static IEnumerable<MethodInfo> TargetMethods()
{
const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public;
yield return typeof(NCharacterSelectScreen).GetMethod("InitializeMultiplayerAsClient", flags)!;
yield return typeof(NCharacterSelectScreen).GetMethod("InitializeMultiplayerAsHost", flags)!;
yield return typeof(NDailyRunScreen).GetMethod("InitializeMultiplayerAsClient", flags)!;
yield return typeof(NDailyRunScreen).GetMethod("InitializeMultiplayerAsHost", flags)!;
yield return typeof(NCustomRunScreen).GetMethod("InitializeMultiplayerAsClient", flags)!;
yield return typeof(NCustomRunScreen).GetMethod("InitializeMultiplayerAsHost", flags)!;
}
private static void Prefix(object __instance, INetGameService gameService)
private static void Prefix(NSubmenu __instance, INetGameService gameService)
{
if (gameService.Platform == PlatformType.None)
{
@@ -47,5 +69,84 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs.Screens
}
}
}
private static void Postfix(NSubmenu __instance, INetGameService gameService)
{
if (__instance.GetNode("IPAddressPanel") is IPAddressInfoPanel ipAddressInfoPanel)
{
if (gameService.Platform == PlatformType.None)
{
ipAddressInfoPanel.Initialize();
ipAddressInfoPanel.Visible = true;
}
else
{
ipAddressInfoPanel.Visible = false;
}
}
}
}
[HarmonyPatch]
internal class RunScreenInitializeAsClientPatchs
{
private static IEnumerable<MethodInfo> TargetMethods()
{
const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public;
yield return typeof(NCharacterSelectScreen).GetMethod("InitializeMultiplayerAsClient", flags)!;
yield return typeof(NDailyRunScreen).GetMethod("InitializeMultiplayerAsClient", flags)!;
yield return typeof(NCustomRunScreen).GetMethod("InitializeMultiplayerAsClient", flags)!;
}
private static void Prefix(NSubmenu __instance, INetGameService gameService)
{
if (gameService.Platform == PlatformType.None)
{
var runScreenService = RunScreenService.Instance;
switch (__instance)
{
case NCharacterSelectScreen characterSelectScreen:
runScreenService.CharacterSelectScreen = characterSelectScreen;
break;
case NDailyRunScreen dailyRunScreen:
runScreenService.DailyRunScreen = dailyRunScreen;
break;
case NCustomRunScreen customRunScreen:
runScreenService.CustomRunScreen = customRunScreen;
break;
}
}
}
private static void Postfix(NSubmenu __instance)
{
if (__instance.GetNode("IPAddressPanel") is IPAddressInfoPanel ipAddressInfoPanel)
{
ipAddressInfoPanel.Visible = false;
}
}
}
[HarmonyPatch]
internal class RunScreenInitializeSingleplayerPatchs
{
private static IEnumerable<MethodInfo> TargetMethods()
{
const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public;
yield return typeof(NCharacterSelectScreen).GetMethod("InitializeSingleplayer", flags)!;
yield return typeof(NDailyRunScreen).GetMethod("InitializeSingleplayer", flags)!;
yield return typeof(NCustomRunScreen).GetMethod("InitializeSingleplayer", flags)!;
}
private static void Postfix(NSubmenu __instance)
{
if (__instance.GetNode("IPAddressPanel") is IPAddressInfoPanel ipAddressInfoPanel)
{
ipAddressInfoPanel.Visible = false;
}
}
}
}