about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--AnodyneArchipelago/AnodyneArchipelago.csproj3
-rw-r--r--AnodyneArchipelago/ArchipelagoManager.cs110
-rw-r--r--AnodyneArchipelago/ArchipelagoTreasure.cs21
-rw-r--r--AnodyneArchipelago/Locations.cs20
-rw-r--r--AnodyneArchipelago/Plugin.cs51
5 files changed, 203 insertions, 2 deletions
diff --git a/AnodyneArchipelago/AnodyneArchipelago.csproj b/AnodyneArchipelago/AnodyneArchipelago.csproj index 5ad5e82..abe6c23 100644 --- a/AnodyneArchipelago/AnodyneArchipelago.csproj +++ b/AnodyneArchipelago/AnodyneArchipelago.csproj
@@ -32,5 +32,8 @@
32 <Reference Include="BepInEx.NET.Common"> 32 <Reference Include="BepInEx.NET.Common">
33 <HintPath>..\..\BepInEx\bin\NET.Framework\net462\BepInEx.NET.Common.dll</HintPath> 33 <HintPath>..\..\BepInEx\bin\NET.Framework\net462\BepInEx.NET.Common.dll</HintPath>
34 </Reference> 34 </Reference>
35 <Reference Include="FNA">
36 <HintPath>..\..\..\SteamLibrary\steamapps\common\Anodyne\Remake\FNA.dll</HintPath>
37 </Reference>
35 </ItemGroup> 38 </ItemGroup>
36</Project> 39</Project>
diff --git a/AnodyneArchipelago/ArchipelagoManager.cs b/AnodyneArchipelago/ArchipelagoManager.cs index 8c107a3..4ffa3af 100644 --- a/AnodyneArchipelago/ArchipelagoManager.cs +++ b/AnodyneArchipelago/ArchipelagoManager.cs
@@ -1,12 +1,21 @@
1using Archipelago.MultiClient.Net; 1using AnodyneSharp.Entities;
2using AnodyneSharp.Registry;
3using Archipelago.MultiClient.Net;
2using Archipelago.MultiClient.Net.Enums; 4using Archipelago.MultiClient.Net.Enums;
5using Archipelago.MultiClient.Net.Models;
6using Archipelago.MultiClient.Net.Packets;
3using System; 7using System;
8using System.Collections.Generic;
9using System.Linq;
4 10
5namespace AnodyneArchipelago 11namespace AnodyneArchipelago
6{ 12{
7 internal class ArchipelagoManager 13 internal class ArchipelagoManager
8 { 14 {
9 private static ArchipelagoSession _session; 15 private static ArchipelagoSession _session;
16 private static int _itemIndex = 0;
17
18 private static readonly Queue<NetworkItem> _itemsToCollect = new();
10 19
11 public static void Connect(string url, string slotName, string password) 20 public static void Connect(string url, string slotName, string password)
12 { 21 {
@@ -38,6 +47,105 @@ namespace AnodyneArchipelago
38 47
39 return; 48 return;
40 } 49 }
50
51 _itemIndex = 0;
52 _itemsToCollect.Clear();
53 }
54
55 public static void Disconnect()
56 {
57 if (_session == null)
58 {
59 return;
60 }
61
62 _session.Socket.DisconnectAsync();
63 _session = null;
64 }
65
66 public static void SendLocation(string location)
67 {
68 if (_session == null)
69 {
70 Plugin.Instance.Log.LogError("Attempted to send location while disconnected");
71 return;
72 }
73
74 _session.Locations.CompleteLocationChecks(_session.Locations.GetLocationIdFromName("Anodyne", location));
75 }
76
77 public static void Update()
78 {
79 if (_session == null)
80 {
81 // We're not connected.
82 return;
83 }
84
85 if (_session.Items.AllItemsReceived.Count > _itemIndex)
86 {
87 for (int i = _itemIndex; i < _session.Items.AllItemsReceived.Count; i++)
88 {
89 string itemKey = $"ArchipelagoItem-{i}";
90 if (GlobalState.events.GetEvent(itemKey) != 0)
91 {
92 continue;
93 }
94
95 GlobalState.events.SetEvent(itemKey, 1);
96
97 NetworkItem item = _session.Items.AllItemsReceived[i];
98 _itemsToCollect.Enqueue(item);
99 }
100 }
101
102 if (_itemsToCollect.Count > 0)
103 {
104 NetworkItem item = _itemsToCollect.Dequeue();
105 HandleItem(item);
106 }
107 }
108
109 private static string GetMapNameForDungeon(string dungeon)
110 {
111 switch (dungeon)
112 {
113 case "Temple of the Seeing One": return "BEDROOM";
114 case "Apartment": return "APARTMENT";
115 case "Mountain Cavern": return "CROWD";
116 case "Hotel": return "HOTEL";
117 case "Red Grotto": return "REDCAVE";
118 case "Circus": return "CIRCUS";
119 default: return "STREET";
120 }
121 }
122
123 private static void HandleItem(NetworkItem item)
124 {
125 string itemName = _session.Items.GetItemName(item.Item);
126
127 if (itemName.StartsWith("Small Key"))
128 {
129 string dungeonName = itemName.Substring(11);
130 dungeonName = dungeonName.Substring(0, dungeonName.Length - 1);
131
132 string mapName = GetMapNameForDungeon(dungeonName);
133 GlobalState.inventory.AddMapKey(mapName, 1);
134 } else if (itemName == "Green Key")
135 {
136 GlobalState.inventory.BigKeyStatus[0] = true;
137 }
138 else if (itemName == "Blue Key")
139 {
140 GlobalState.inventory.BigKeyStatus[2] = true;
141 }
142 else if (itemName == "Red Key")
143 {
144 GlobalState.inventory.BigKeyStatus[1] = true;
145 } else if (itemName == "Jump Shoes")
146 {
147 GlobalState.inventory.CanJump = true;
148 }
41 } 149 }
42 } 150 }
43} 151}
diff --git a/AnodyneArchipelago/ArchipelagoTreasure.cs b/AnodyneArchipelago/ArchipelagoTreasure.cs new file mode 100644 index 0000000..6d000e8 --- /dev/null +++ b/AnodyneArchipelago/ArchipelagoTreasure.cs
@@ -0,0 +1,21 @@
1using AnodyneSharp.Entities.Gadget.Treasures;
2using Microsoft.Xna.Framework;
3
4namespace AnodyneArchipelago
5{
6 internal class ArchipelagoTreasure : Treasure
7 {
8 private string _location;
9
10 public ArchipelagoTreasure(string location, Vector2 pos) : base("item_jump_shoes", pos, 0, -1)
11 {
12 _location = location;
13 }
14
15 public override void GetTreasure()
16 {
17 base.GetTreasure();
18 ArchipelagoManager.SendLocation(_location);
19 }
20 }
21}
diff --git a/AnodyneArchipelago/Locations.cs b/AnodyneArchipelago/Locations.cs new file mode 100644 index 0000000..46e2471 --- /dev/null +++ b/AnodyneArchipelago/Locations.cs
@@ -0,0 +1,20 @@
1
2using System;
3using System.Collections.Generic;
4
5namespace AnodyneArchipelago
6{
7 internal class Locations
8 {
9 public static Dictionary<Guid, string> LocationsByGuid = new()
10 {
11 {new Guid("40de36cf-9238-f8b0-7a57-c6c8ca465cc2"), "Temple of the Seeing One - Entrance Chest" },
12 {new Guid("621c284f-cbd0-74c3-f51b-2a9fdde8d4d7"), "Temple of the Seeing One - Rock-Surrounded Chest" },
13 {new Guid("401939a4-41ba-e07e-3ba2-dc22513dcc5c"), "Temple of the Seeing One - Dark Room Chest" },
14 {new Guid("88d0a7b8-eeab-c45f-324e-f1c7885c41ce"), "Temple of the Seeing One - Shieldy Room Chest" },
15 {new Guid("0bce5346-48a2-47f9-89cb-3f59d9d0b7d2"), "Temple of the Seeing One - Boss Chest" },
16 {new Guid("d41f2750-e3c7-bbb4-d650-fafc190ebd32"), "Temple of the Seeing One - After Statue Left Chest" },
17 {new Guid("3167924e-5d52-1cd6-d6f4-b8e0e328215b"), "Temple of the Seeing One - After Statue Right Chest" },
18 };
19 }
20}
diff --git a/AnodyneArchipelago/Plugin.cs b/AnodyneArchipelago/Plugin.cs index 7375503..f49ba35 100644 --- a/AnodyneArchipelago/Plugin.cs +++ b/AnodyneArchipelago/Plugin.cs
@@ -1,7 +1,12 @@
1using BepInEx; 1using AnodyneSharp;
2using AnodyneSharp.Entities;
3using AnodyneSharp.Entities.Gadget;
4using AnodyneSharp.Entities.Gadget.Treasures;
5using BepInEx;
2using BepInEx.NET.Common; 6using BepInEx.NET.Common;
3using HarmonyLib; 7using HarmonyLib;
4using HarmonyLib.Tools; 8using HarmonyLib.Tools;
9using System;
5using System.Reflection; 10using System.Reflection;
6 11
7namespace AnodyneArchipelago 12namespace AnodyneArchipelago
@@ -26,6 +31,15 @@ namespace AnodyneArchipelago
26 } 31 }
27 } 32 }
28 33
34 [HarmonyPatch(typeof(AnodyneGame), "Update")]
35 class GameUpdatePatch
36 {
37 static void Postfix()
38 {
39 ArchipelagoManager.Update();
40 }
41 }
42
29 [HarmonyPatch(typeof(AnodyneSharp.States.PlayState), nameof(AnodyneSharp.States.PlayState.Create))] 43 [HarmonyPatch(typeof(AnodyneSharp.States.PlayState), nameof(AnodyneSharp.States.PlayState.Create))]
30 class PlayStateCreatePatch 44 class PlayStateCreatePatch
31 { 45 {
@@ -36,4 +50,39 @@ namespace AnodyneArchipelago
36 ArchipelagoManager.Connect("localhost:38281", "Anodyne", ""); 50 ArchipelagoManager.Connect("localhost:38281", "Anodyne", "");
37 } 51 }
38 } 52 }
53
54 [HarmonyPatch(typeof(TreasureChest), nameof(TreasureChest.PlayerInteraction))]
55 class ChestInteractPatch
56 {
57 static void Prefix(TreasureChest __instance)
58 {
59 Type chestType = typeof(TreasureChest);
60 FieldInfo presetField = chestType.GetField("_preset", BindingFlags.NonPublic | BindingFlags.Instance);
61 EntityPreset preset = presetField.GetValue(__instance) as EntityPreset;
62 Plugin.Instance.Log.LogInfo($"Touched chest: {preset.EntityID.ToString()}");
63 }
64 }
65
66 [HarmonyPatch(typeof(TreasureChest), "SetTreasure")]
67 class ChestSetTreasurePatch
68 {
69 static bool Prefix(TreasureChest __instance)
70 {
71 Type chestType = typeof(TreasureChest);
72 FieldInfo presetField = chestType.GetField("_preset", BindingFlags.NonPublic | BindingFlags.Instance);
73 EntityPreset preset = presetField.GetValue(__instance) as EntityPreset;
74
75 if (Locations.LocationsByGuid.ContainsKey(preset.EntityID))
76 {
77 BaseTreasure treasure = new ArchipelagoTreasure(Locations.LocationsByGuid[preset.EntityID], __instance.Position);
78
79 FieldInfo treasureField = chestType.GetField("_treasure", BindingFlags.NonPublic | BindingFlags.Instance);
80 treasureField.SetValue(__instance, treasure);
81
82 return false;
83 }
84
85 return true;
86 }
87 }
39} 88}