Skip to content

Commit

Permalink
implement resources as filler items
Browse files Browse the repository at this point in the history
  • Loading branch information
Berserker66 committed May 25, 2023
1 parent 8d938ca commit 084256a
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 132 deletions.
5 changes: 3 additions & 2 deletions mod/APData.cs → mod/APConnectInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

namespace Archipelago
{
public class APData : APLastConnectInfo
public class APConnectInfo : APLastConnectInfo
{
public long index;
public HashSet<long> @checked = new HashSet<long>();
public HashSet<long> @checked = new ();
public bool death_link = false;
public Dictionary<long, HashSet<long>> resources_granted = new ();

public void FillFromLastConnect(APLastConnectInfo lastConnectInfo)
{
Expand Down
147 changes: 52 additions & 95 deletions mod/APState.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
Expand All @@ -17,6 +16,7 @@

namespace Archipelago
{

public static class APState
{
public struct Location
Expand All @@ -38,12 +38,9 @@ public enum State
{ "infected", "Infection_Progress4" },
};

public static int[] AP_VERSION = new int[] { 0, 4, 0 };
public static APData ServerData = new APData();
public static int[] AP_VERSION = new int[] { 0, 4, 1 };
public static APConnectInfo ServerConnectInfo = new APConnectInfo();
public static DeathLinkService DeathLinkService = null;
public static Dictionary<long, TechType> ITEM_CODE_TO_TECHTYPE = new ();
public static Dictionary<long, Location> LOCATIONS = new ();
public static Dictionary<long, List<long>> GROUP_ITEMS = new ();
public static bool DeathLinkKilling = false; // indicates player is currently getting DeathLinked
public static Dictionary<string, int> archipelago_indexes = new ();
public static float unlock_dequeue_timeout = 0.0f;
Expand Down Expand Up @@ -156,9 +153,6 @@ public enum State
};

public static TrackerMode TrackedMode = TrackerMode.Logical;
public static Dictionary<string, long> Encyclopdia;
public static Dictionary<TechType, List<long>> LogicDict;

public static HashSet<TechType> TechFragmentsToDestroy = new HashSet<TechType>();

#if DEBUG
Expand Down Expand Up @@ -195,87 +189,19 @@ public static string InspectGameObject(GameObject gameObject)
}
#endif

public static T ReadJSON<T>(string filename)
{
try
{
var reader = File.OpenText(BepInEx.Paths.PluginPath+"/Archipelago/" + filename + ".json");
var content = reader.ReadToEnd();
reader.Close();
var data = JsonConvert.DeserializeObject<T>(content);
return data;
}
catch (Exception e)
{
Debug.LogError("Could not read " + filename + ".json\n" + e);
return default;
}
}

public static void Init()
{
// Load items.json
{
var data = ReadJSON<Dictionary<int, string>>("items");
foreach (var itemJson in data)
{
// not all tech types exist in both games
var success = Enum.TryParse(itemJson.Value, out TechType tech);
if (success)
{
ITEM_CODE_TO_TECHTYPE[itemJson.Key] = tech;
}
}
}
// Load group_items.json
{
GROUP_ITEMS = ReadJSON<Dictionary<long, List<long>>>("group_items");
}
// Load locations.json
{
var data = ReadJSON<Dictionary<int, Dictionary<string, float>>>("locations");

foreach (var locationJson in data)
{
Location location = new Location();
location.ID = locationJson.Key;
var vec = locationJson.Value;
location.Position = new Vector3(
vec["x"],
vec["y"],
vec["z"]
);
LOCATIONS.Add(location.ID, location);
}
}
// Load encyclopedia.json
{
Encyclopdia = ReadJSON<Dictionary<string, long>>("encyclopedia");
}
// Load logic.json
{
LogicDict = ReadJSON<Dictionary<TechType, List<long>>>("logic");
}

// launch thread
TrackerProcessing = new Thread(TrackerThread.DoWork);
TrackerProcessing.IsBackground = true;
TrackerProcessing.Start();
}

public static bool Connect()
{
if (Authenticated)
{
return true;
}

if (ServerData.host_name is null || ServerData.host_name.Length == 0)
if (ServerConnectInfo.host_name is null || ServerConnectInfo.host_name.Length == 0)
{
return false;
}

string hostName = ServerData.host_name;
string hostName = ServerConnectInfo.host_name;

// Start the archipelago session.
Session = ArchipelagoSessionFactory.CreateSession(hostName);
Expand All @@ -286,12 +212,12 @@ public static bool Connect()
HashSet<TechType> vanillaTech = new HashSet<TechType>();
LoginResult loginResult = Session.TryConnectAndLogin(
"Subnautica",
ServerData.slot_name,
ServerConnectInfo.slot_name,
ItemsHandlingFlags.AllItems,
new Version(AP_VERSION[0], AP_VERSION[1], AP_VERSION[2]),
null,
"",
ServerData.password == "" ? null : ServerData.password);
ServerConnectInfo.password == "" ? null : ServerConnectInfo.password);

if (loginResult is LoginSuccessful loginSuccess)
{
Expand All @@ -300,7 +226,7 @@ public static bool Connect()
BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(storage);
if (rawPath != null)
{
ServerData.GetAsLastConnect().WriteToFile(rawPath + "/archipelago_last_connection.json");
ServerConnectInfo.GetAsLastConnect().WriteToFile(rawPath + "/archipelago_last_connection.json");
}
else
{
Expand Down Expand Up @@ -329,7 +255,7 @@ public static bool Connect()


Debug.Log("SlotData: " + JsonConvert.SerializeObject(loginSuccess.SlotData));
ServerData.death_link = Convert.ToInt32(loginSuccess.SlotData["death_link"]) > 0;
ServerConnectInfo.death_link = Convert.ToInt32(loginSuccess.SlotData["death_link"]) > 0;
set_deathlink();

}
Expand Down Expand Up @@ -394,7 +320,7 @@ public static bool CheckLocation(Vector3 position)
{
long closest_id = -1;
float closestDist = 100000.0f;
foreach (var location in LOCATIONS)
foreach (var location in ArchipelagoData.Locations)
{
var dist = Vector3.Distance(location.Value.Position, position);
if (dist < closestDist && dist < 1.0f)
Expand Down Expand Up @@ -429,43 +355,69 @@ public static bool CheckLocation(Vector3 position)

public static void SendLocID(long id)
{
if (ServerData.@checked.Add(id))
if (ServerConnectInfo.@checked.Add(id))
{
Task.Run(() => {Session.Locations.CompleteLocationChecksAsync(
ServerData.@checked.Except(Session.Locations.AllLocationsChecked).ToArray()); }).ConfigureAwait(false);
ServerConnectInfo.@checked.Except(Session.Locations.AllLocationsChecked).ToArray()); }).ConfigureAwait(false);
}
}

public static void Resync()
{
Debug.Log("Running Item resync with " + Session.Items.AllItemsReceived.Count + " items.");
var done = new HashSet<long>();
foreach (var networkItem in Session.Items.AllItemsReceived)
for (int i = 0; i < Session.Items.AllItemsReceived.Count; i++)
{
if (!done.Contains(networkItem.Item))
var itemID = Session.Items.AllItemsReceived[i].Item;
if (ArchipelagoData.ItemCodeToItemType[itemID] == ArchipelagoItemType.Resource || !done.Contains(itemID))
{
Unlock(networkItem.Item);
done.Add(networkItem.Item);
Unlock(itemID, i);
done.Add(itemID);
}
}
}

public static void Unlock(long apItemID)
public static void Unlock(long apItemID, long index)
{
if (GROUP_ITEMS.TryGetValue(apItemID, out var groupUnlock))
if (ArchipelagoData.GroupItems.TryGetValue(apItemID, out var groupUnlock))
{
foreach (var subUnlock in groupUnlock)
{
Unlock(subUnlock);
Unlock(subUnlock, index);
}
return;
}

ArchipelagoData.ItemCodeToTechType.TryGetValue(apItemID, out var techType);
if (ArchipelagoData.ItemCodeToItemType[apItemID] == ArchipelagoItemType.Resource)
{
HashSet<long> set;
if (!ServerConnectInfo.resources_granted.TryGetValue(apItemID, out set))
{
set = new();
ServerConnectInfo.resources_granted[apItemID] = set;
}
if (set.Contains(index))
{
// already given resources
return;
}

set.Add(index);
for (int i = 0; i < set.Count; i++)
{
Inventory.main.StartCoroutine(PickUp(techType));
}

return;
}
ITEM_CODE_TO_TECHTYPE.TryGetValue(apItemID, out var techType);

if (techType == TechType.None || KnownTech.Contains(techType))
{
// Unknown item ID or already known technology.
return;
}

if (PDAScanner.IsFragment(techType))
{
PDAScanner.EntryData entryData = PDAScanner.GetEntryData(techType);
Expand Down Expand Up @@ -556,6 +508,11 @@ private static IEnumerator PickUp(TechType techType)
Debug.LogError("Object " + techType + " failed to be created.");
yield break;
}
// in case it can't be picked up, dump it right in front of player for obvious problem.
gameObject.transform.position = MainCamera.camera.transform.position +
MainCamera.camera.transform.forward * 3f;
// This seems to fill batteries to default values when crafted.
CrafterLogic.NotifyCraftEnd(gameObject, techType);

Pickupable pickupable = gameObject.GetComponent<Pickupable>();
if (pickupable == null)
Expand Down Expand Up @@ -622,7 +579,7 @@ public static void set_deathlink()
DeathLinkService.OnDeathLinkReceived += DeathLinkReceived;
}

if (ServerData.death_link)
if (ServerConnectInfo.death_link)
{
DeathLinkService.EnableDeathLink();
}
Expand Down

0 comments on commit 084256a

Please sign in to comment.