From 189fcfc1087764961e61c470ffea642ff46d164d Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Sat, 25 May 2024 13:11:17 -0400 Subject: You can connect now! --- AnodyneArchipelago/ArchipelagoManager.cs | 65 +++++++------- AnodyneArchipelago/ArchipelagoTreasure.cs | 2 +- AnodyneArchipelago/Menu/ConnectionState.cs | 118 ++++++++++++++++++++++++++ AnodyneArchipelago/Menu/MenuState.cs | 38 +++++++++ AnodyneArchipelago/Patches/GameplayPatches.cs | 10 +-- AnodyneArchipelago/Patches/StatePatches.cs | 22 +++-- AnodyneArchipelago/Plugin.cs | 1 + 7 files changed, 214 insertions(+), 42 deletions(-) create mode 100644 AnodyneArchipelago/Menu/ConnectionState.cs diff --git a/AnodyneArchipelago/ArchipelagoManager.cs b/AnodyneArchipelago/ArchipelagoManager.cs index 0b7c478..7c67114 100644 --- a/AnodyneArchipelago/ArchipelagoManager.cs +++ b/AnodyneArchipelago/ArchipelagoManager.cs @@ -11,53 +11,48 @@ using Archipelago.MultiClient.Net.Packets; using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace AnodyneArchipelago { - internal class ArchipelagoManager + public class ArchipelagoManager { - private static ArchipelagoSession _session; - private static int _itemIndex = 0; + private ArchipelagoSession _session; + private int _itemIndex = 0; + private string _seedName; - private static readonly Queue _itemsToCollect = new(); + private readonly Queue _itemsToCollect = new(); - public static void Connect(string url, string slotName, string password) + public async Task Connect(string url, string slotName, string password) { LoginResult result; try { _session = ArchipelagoSessionFactory.CreateSession(url); _session.MessageLog.OnMessageReceived += OnMessageReceived; - result = _session.TryConnectAndLogin("Anodyne", slotName, ItemsHandlingFlags.AllItems, null, null, null, password == "" ? null : password); + + RoomInfoPacket roomInfoPacket = await _session.ConnectAsync(); + _seedName = roomInfoPacket.SeedName; + + result = await _session.LoginAsync("Anodyne", slotName, ItemsHandlingFlags.AllItems, null, null, null, password == "" ? null : password); } catch (Exception e) { result = new LoginFailure(e.GetBaseException().Message); } - if (!result.Successful) - { - LoginFailure failure = result as LoginFailure; - string errorMessage = $"Failed to connect to {url} as {slotName}:"; - foreach (string error in failure.Errors) - { - errorMessage += $"\n {error}"; - } - foreach (ConnectionRefusedError error in failure.ErrorCodes) - { - errorMessage += $"\n {error}"; - } - - Plugin.Instance.Log.LogError(errorMessage); - - return; - } - _itemIndex = 0; _itemsToCollect.Clear(); + + return result; + } + + ~ArchipelagoManager() + { + Disconnect(); } - public static void Disconnect() + public void Disconnect() { if (_session == null) { @@ -68,7 +63,17 @@ namespace AnodyneArchipelago _session = null; } - public static void SendLocation(string location) + public string GetSeed() + { + return _seedName; + } + + public int GetPlayer() + { + return _session.ConnectionInfo.Slot; + } + + public void SendLocation(string location) { if (_session == null) { @@ -79,7 +84,7 @@ namespace AnodyneArchipelago _session.Locations.CompleteLocationChecks(_session.Locations.GetLocationIdFromName("Anodyne", location)); } - public static void Update() + public void Update() { if (_session == null) { @@ -104,7 +109,7 @@ namespace AnodyneArchipelago } } - if (_itemsToCollect.Count > 0 && (GlobalState.Dialogue == null || GlobalState.Dialogue == "") && !GlobalState.ScreenTransition) + if (_itemsToCollect.Count > 0 && (GlobalState.Dialogue == null || GlobalState.Dialogue == "") && !GlobalState.ScreenTransition && Plugin.Player != null && GlobalState.black_overlay.alpha == 0f) { NetworkItem item = _itemsToCollect.Dequeue(); HandleItem(item); @@ -125,7 +130,7 @@ namespace AnodyneArchipelago } } - private static void HandleItem(NetworkItem item) + private void HandleItem(NetworkItem item) { if (item.Player == _session.ConnectionInfo.Slot) { @@ -223,7 +228,7 @@ namespace AnodyneArchipelago GlobalState.Dialogue = message; } - private static void OnMessageReceived(LogMessage message) + private void OnMessageReceived(LogMessage message) { switch (message) { diff --git a/AnodyneArchipelago/ArchipelagoTreasure.cs b/AnodyneArchipelago/ArchipelagoTreasure.cs index b3812f2..90f979c 100644 --- a/AnodyneArchipelago/ArchipelagoTreasure.cs +++ b/AnodyneArchipelago/ArchipelagoTreasure.cs @@ -33,7 +33,7 @@ namespace AnodyneArchipelago base.GetTreasure(); } - ArchipelagoManager.SendLocation(_location); + Plugin.ArchipelagoManager.SendLocation(_location); } } } diff --git a/AnodyneArchipelago/Menu/ConnectionState.cs b/AnodyneArchipelago/Menu/ConnectionState.cs new file mode 100644 index 0000000..877213f --- /dev/null +++ b/AnodyneArchipelago/Menu/ConnectionState.cs @@ -0,0 +1,118 @@ +using AnodyneSharp.Input; +using AnodyneSharp.Resources; +using AnodyneSharp.Sounds; +using AnodyneSharp.States; +using AnodyneSharp.UI; +using AnodyneSharp.UI.Font; +using AnodyneSharp.UI.Text; +using Archipelago.MultiClient.Net; +using Archipelago.MultiClient.Net.Enums; +using Microsoft.Xna.Framework; +using System.Reflection; +using System.Threading.Tasks; + +namespace AnodyneArchipelago.Menu +{ + internal class ConnectionState : State + { + public delegate void SuccessEvent(ArchipelagoManager archipelagoManager); + + private readonly SuccessEvent _successFunc; + + private Task _connectionTask; + private ArchipelagoManager _archipelago = new(); + + private TextWriter _textWriter; + private UIEntity _bgBox; + private readonly SpriteFont _font; + + private string _text = "Connecting..."; + + public ConnectionState(string apServer, string apSlot, string apPassword, SuccessEvent successFunc) + { + _successFunc = successFunc; + + _connectionTask = Task.Run(() => _archipelago.Connect(apServer, apSlot, apPassword)); + + _font = FontManager.InitFont(new Color(226, 226, 226), true); + + _textWriter = new(20, 44, 128, 100) + { + drawLayer = AnodyneSharp.Drawing.DrawOrder.TEXT + }; + _textWriter.SetSpriteFont(_font, ResourceManager.GetTexture("consoleButtons")); + + _bgBox = new UIEntity(new Vector2(16f, 40f), "pop_menu", 16, 16, AnodyneSharp.Drawing.DrawOrder.TEXTBOX); + UpdateDisplay(); + } + + public override void Update() + { + if (_connectionTask != null && _connectionTask.IsCompleted) + { + LoginResult result = _connectionTask.Result; + + if (result.Successful) + { + Exit = true; + _successFunc(_archipelago); + return; + } + else + { + LoginFailure failure = result as LoginFailure; + string errorMessage = ""; + foreach (string error in failure.Errors) + { + errorMessage += error; + errorMessage += "\n"; + } + foreach (ConnectionRefusedError error in failure.ErrorCodes) + { + errorMessage += error.ToString(); + errorMessage += "\n"; + } + + if (errorMessage.Length > 0) + { + errorMessage = errorMessage.Substring(0, errorMessage.Length - 1); + } + else + { + errorMessage = "Unknown error during connection."; + } + + _text = errorMessage; + _connectionTask = null; + + UpdateDisplay(); + } + } + + if (KeyInput.JustPressedRebindableKey(KeyFunctions.Accept) || KeyInput.JustPressedRebindableKey(KeyFunctions.Cancel)) + { + Exit = true; + SoundManager.PlaySoundEffect("menu_select"); + } + } + + public override void DrawUI() + { + _bgBox.Draw(); + _textWriter.Draw(); + } + + private void UpdateDisplay() + { + _textWriter.Text = _text; + _textWriter.ProgressTextToEnd(); + + FieldInfo linesField = typeof(TextWriter).GetField("_line", BindingFlags.NonPublic | BindingFlags.Instance); + int lineValue = (int)linesField.GetValue(_textWriter); + + int innerHeight = (lineValue + 1) * _font.lineSeparation; + + _bgBox = new UIEntity(new Vector2(16f, 40f), "pop_menu", 136, innerHeight + 8, AnodyneSharp.Drawing.DrawOrder.TEXTBOX); + } + } +} diff --git a/AnodyneArchipelago/Menu/MenuState.cs b/AnodyneArchipelago/Menu/MenuState.cs index b9ee0dd..cabb94b 100644 --- a/AnodyneArchipelago/Menu/MenuState.cs +++ b/AnodyneArchipelago/Menu/MenuState.cs @@ -33,6 +33,9 @@ namespace AnodyneArchipelago.Menu private int _selectorIndex = 0; + private bool _fadingOut = false; + private bool _isNewGame; + public override void Create() { _selector = new(); @@ -65,6 +68,18 @@ namespace AnodyneArchipelago.Menu public override void Update() { + if (_fadingOut) + { + GlobalState.black_overlay.ChangeAlpha(0.72f); + + if (GlobalState.black_overlay.alpha == 1.0) + { + ChangeStateEvent(_isNewGame ? AnodyneSharp.AnodyneGame.GameState.Intro : AnodyneSharp.AnodyneGame.GameState.Game); + } + + return; + } + if (_substate != null) { _substate.Update(); @@ -217,6 +232,9 @@ namespace AnodyneArchipelago.Menu case 2: _substate = new TextEntry("Password:", _apPassword, (string value) => { _apPassword = value; UpdateLabels(); }); break; + case 4: + _substate = new ConnectionState(_apServer, _apSlot, _apPassword, OnConnected); + break; case 6: GlobalState.ClosingGame = true; break; @@ -231,5 +249,25 @@ namespace AnodyneArchipelago.Menu { } + + private void OnConnected(ArchipelagoManager archipelagoManager) + { + Plugin.ArchipelagoManager = archipelagoManager; + + GlobalState.Save saveFile = GlobalState.Save.GetSave(string.Format("{0}Saves/Save_zzAP{1}_{2}.dat", GameConstants.SavePath, Plugin.ArchipelagoManager.GetSeed(), Plugin.ArchipelagoManager.GetPlayer())); + + GlobalState.ResetValues(); + if (saveFile != null) + { + GlobalState.LoadSave(saveFile); + _isNewGame = false; + } + else + { + _isNewGame = true; + } + + _fadingOut = true; + } } } diff --git a/AnodyneArchipelago/Patches/GameplayPatches.cs b/AnodyneArchipelago/Patches/GameplayPatches.cs index ada4159..9db87a5 100644 --- a/AnodyneArchipelago/Patches/GameplayPatches.cs +++ b/AnodyneArchipelago/Patches/GameplayPatches.cs @@ -69,15 +69,15 @@ namespace AnodyneArchipelago.Patches if (preset.Frame == 0) { - ArchipelagoManager.SendLocation("Temple of the Seeing One - Green Key"); + Plugin.ArchipelagoManager.SendLocation("Temple of the Seeing One - Green Key"); } else if (preset.Frame == 1) { - ArchipelagoManager.SendLocation("Red Grotto - Red Key"); + Plugin.ArchipelagoManager.SendLocation("Red Grotto - Red Key"); } else if (preset.Frame == 2) { - ArchipelagoManager.SendLocation("Mountain Cavern - Blue Key"); + Plugin.ArchipelagoManager.SendLocation("Mountain Cavern - Blue Key"); } } } @@ -134,7 +134,7 @@ namespace AnodyneArchipelago.Patches if (Locations.LocationsByGuid.ContainsKey(preset.EntityID)) { - ArchipelagoManager.SendLocation(Locations.LocationsByGuid[preset.EntityID]); + Plugin.ArchipelagoManager.SendLocation(Locations.LocationsByGuid[preset.EntityID]); } } } @@ -221,7 +221,7 @@ namespace AnodyneArchipelago.Patches if (Locations.LocationsByGuid.ContainsKey(preset.EntityID)) { - ArchipelagoManager.SendLocation(Locations.LocationsByGuid[preset.EntityID]); + Plugin.ArchipelagoManager.SendLocation(Locations.LocationsByGuid[preset.EntityID]); } } } diff --git a/AnodyneArchipelago/Patches/StatePatches.cs b/AnodyneArchipelago/Patches/StatePatches.cs index 4b29295..40b30fe 100644 --- a/AnodyneArchipelago/Patches/StatePatches.cs +++ b/AnodyneArchipelago/Patches/StatePatches.cs @@ -8,6 +8,7 @@ using AnodyneSharp.Drawing.Effects; using AnodyneSharp.States.MainMenu; using static AnodyneSharp.AnodyneGame; using AnodyneSharp.Drawing; +using System.IO; namespace AnodyneArchipelago.Patches { @@ -16,7 +17,10 @@ namespace AnodyneArchipelago.Patches { static void Postfix() { - ArchipelagoManager.Update(); + if (Plugin.ArchipelagoManager != null) + { + Plugin.ArchipelagoManager.Update(); + } } } @@ -63,6 +67,17 @@ namespace AnodyneArchipelago.Patches } } + [HarmonyPatch(typeof(GlobalState.Save), nameof(GlobalState.Save.SaveTo))] + class SaveToPatch + { + static bool Prefix(GlobalState.Save __instance) + { + File.WriteAllText(string.Format("{0}Saves/Save_zzAP{1}_{2}.dat", GameConstants.SavePath, Plugin.ArchipelagoManager.GetSeed(), Plugin.ArchipelagoManager.GetPlayer()), __instance.ToString()); + + return false; + } + } + [HarmonyPatch(typeof(PlayState), nameof(PlayState.Create))] class PlayStateCreatePatch { @@ -76,11 +91,6 @@ namespace AnodyneArchipelago.Patches GlobalState.events.SetEvent("red_cave_l_ss", 999); GlobalState.events.SetEvent("red_cave_n_ss", 999); GlobalState.events.SetEvent("red_cave_r_ss", 999); - - // Connect to archipelago. - Plugin.Instance.Log.LogInfo("Connecting to Archipelago!"); - - ArchipelagoManager.Connect("localhost:38281", "Anodyne", ""); } } } diff --git a/AnodyneArchipelago/Plugin.cs b/AnodyneArchipelago/Plugin.cs index 66f020d..10a30b9 100644 --- a/AnodyneArchipelago/Plugin.cs +++ b/AnodyneArchipelago/Plugin.cs @@ -13,6 +13,7 @@ namespace AnodyneArchipelago { public static Plugin Instance = null; public static Player Player = null; + public static ArchipelagoManager ArchipelagoManager = null; public static string GetVersion() { -- cgit 1.4.1